Welcome to the Java Programming Forums


The professional, friendly Java community. 21,500 members and growing!


The Java Programming Forums are a community of Java programmers from all around the World. Our members have a wide range of skills and they all have one thing in common: A passion to learn and code Java. We invite beginner Java programmers right through to Java professionals to post here and share your knowledge. Become a part of the community, help others, expand your knowledge of Java and enjoy talking with like minded people. Registration is quick and best of all free. We look forward to meeting you.


>> REGISTER NOW TO START POSTING


Members have full access to the forums. Advertisements are removed for registered users.

Results 1 to 7 of 7

Thread: Class hierarchy... giving me a headache, so I could use some help

  1. #1
    Member
    Join Date
    Mar 2011
    Location
    Earth!
    Posts
    77
    Thanks
    2
    Thanked 1 Time in 1 Post

    Default Class hierarchy... giving me a headache, so I could use some help

    Hi all.

    Making a small program that will read a .class file and display information. Using this as a reference point:
    VM Spec The class File Format
    It describes the class file format, hopefully in an accurate way. Anyway, I am trying to figure out a good way to read from the constant pool. If you read that link, in the section about the constant pool, it talks about several structures that are very similar. So I could just use a class hierarchy. Thing is, I am the master of complicating things for myself, and I am not sure what the best way to represent the different stuff would be. For example, here are two of the classes:

    Base class:
    public abstract class CPInfo
    {
    	// Declare the tag holding variable
    	protected int mTag;
     
    	/**
    	 * Returns the tag of this cp info thing
    	 * 
    	 * @return the tag
    	 */
        public int tag()
        {
            return mTag;
        }
     
        /**
         * ============
         * === TAGS ===
         * ============
         */
        public static final int TAG_CLASS = 7;
        public static final int TAG_FIELD_REF = 9;
        public static final int TAG_METHOD_REF = 10;
        public static final int TAG_INTERFACE_METHOD_REF = 11;
        public static final int TAG_STRING = 8;
        public static final int TAG_INTEGER = 3;
        public static final int TAG_FLOAT = 4;
        public static final int TAG_LONG = 5;
        public static final int TAG_DOUBLE = 6;
        public static final int TAG_NAME_AND_TYPE = 12;
        public static final int TAG_UTF8 = 1;
    }

    Represents an integer in the constant pool.
    public class CPInteger extends CPInfo
    {
    	private int mInt;
     
    	public CPInteger(int intval) throws ClassFormatException
    	{
    		super.mTag = CPInfo.TAG_INTEGER;
    		mInt = intval;
    	}
     
    	public int value()
    	{
    		return mInt;
    	}
    }

    Represents a float in the constant pool:
    public class CPFloatInfo extends CPInfo
    {
    	private float mFloat;
     
    	public CPFloatInfo(float floatval)
    	{
    		super.mTag = CPInfo.TAG_FLOAT;
    		mFloat = floatval;
    	}
     
    	public float value()
    	{
    		return mFloat;
    	}
    }
    As you can see, they are basically identical, except that one stores an int and one stores a float. Not happy with it, to be honest, since they are so similar. It feels like I could create a better way to do this. Anyone has a better idea of how to do this? Or is this the best way? I am getting a headache when I think of it too much, lol (figuratively speaking).

    And do note that at the moment I am just trying to replicate the structure of a class file until I get a better grip of what I am actually doing. Have not done this before, so to be honest, I have no idea what I am doing.

    Take care,
    Kerr

    EDIT:

    One option would be to simply have an object in the CPInfo class and then cast it to whatever data I need (in the case of int and float I would use the Integer or Float classes). Could work, but not very type safe. Not that the way I am currently doing it is any better, for that matter...
    Last edited by Kerr; May 23rd, 2011 at 03:02 PM.


  2. #2
    Forum old-timer
    Join Date
    Nov 2008
    Location
    Faversham, Kent, UK
    Posts
    472
    My Mood
    Mellow
    Thanks
    4
    Thanked 58 Times in 54 Posts

    Default Re: Class hierarchy... giving me a headache, so I could use some help

    Quote Originally Posted by Kerr View Post
    ...
    As you can see, they are basically identical, except that one stores an int and one stores a float. Not happy with it, to be honest, since they are so similar. It feels like I could create a better way to do this. Anyone has a better idea of how to do this? Or is this the best way?
    ...
    And do note that at the moment I am just trying to replicate the structure of a class file until I get a better grip of what I am actually doing. Have not done this before, so to be honest, I have no idea what I am doing.
    ...
    One option would be to simply have an object in the CPInfo class and then cast it to whatever data I need (in the case of int and float I would use the Integer or Float classes). Could work, but not very type safe. Not that the way I am currently doing it is any better, for that matter...
    I'd be inclined to use an enum for the tag values, but other than that, it's hard to say - if you don't know what you're doing this for, how can we suggest the best way to go about it? Maybe you need to decide your requirements before trying to any write code...

    In any case, I'd avoid using an Object and casting to some type on demand, but you could use generics to make your CPInfo class deal with whatever types are required, something like this:
    public class CPInfo<T> {
        // Declare the tag holding variable
        protected TAG mTag;
     
        private T mValue;
     
        public CPInfo(T value) throws ClassFormatException, UnknownTagException {
            mValue = value;
     
            // use the type class name to get the correct tag
            mTag = TAG.getTag(value.getClass().getSimpleName());
        }
     
        public T value() {
            return mValue;
        }
     
        /**
         * Returns the tag of this cp info thing
         *
         * @return the tag
         */
        public TAG tag() {
            return mTag;
        }
     
        /**
         * ============ === TAGS === ============
         * Each tag holds its corresponding class name
         */
     
        public static enum TAG {
            TAG_CLASS("Class"),
            TAG_FIELD_REF("Field"),
            TAG_METHOD_REF("Method"),
            TAG_INTERFACE_METHOD_REF("InterfaceMethod"),
            TAG_STRING("String"),
            TAG_INTEGER("Integer"),
            TAG_FLOAT("Float"),
            TAG_LONG("Long"),
            TAG_DOUBLE("Double"),
            TAG_NAME_AND_TYPE("NameAndType"),
            TAG_UTF8("UTF8");
     
            private String className;
     
            // constructor taking class name
            private TAG(String className) {
                this.className = className;
            }
     
            // return the tag for a given class name
            public static TAG getTag(String className) throws UnknownTagException {
                for (TAG tag : TAG.values()) {
                    if (className.equals(tag.className)) {
                        return tag;
                    }
                }
                throw new UnknownTagException(className);
            }
        }
     
        public static void main(String[] args) throws ClassFormatException, UnknownTagException {
            // create a float info object
            CPInfo<Float> floatInfo = new CPInfo<Float>(123.45f);
     
            // Print the tag and value
            CPInfo.TAG tag = floatInfo.tag();
            float value = floatInfo.value();
            System.out.println("Tag = "+tag.name());
            System.out.println("value = "+String.valueOf(value));
        }
    }
    I'm assuming here that you're going to have corresponding classes for each of those tags (e.g. a NameAndType class and a UTF8 class, etc), and that you don't actually need to store primitive types (autoboxing should take care of that). If not, then I don't really know what you want...
    Last edited by dlorde; May 24th, 2011 at 02:00 PM.

  3. #3
    Member
    Join Date
    Mar 2011
    Location
    Earth!
    Posts
    77
    Thanks
    2
    Thanked 1 Time in 1 Post

    Default Re: Class hierarchy... giving me a headache, so I could use some help

    The problem is that I would still have to make some casts, since I would have a list of all CPInfo objects (for example, one containing a float and another an int). However, this gives me an idea. Instead of having a class hierarchy I do it the other way around. Instead of posing as a base class, CPInfo could instead simply contain the tag stating what it is and then store the bytes. The other classes would then simply accept a CPInfo as a parameter to their constructor, and then interpret the bytes as they should do. That way I wouldnīt have to cast them.

    Enums could be good, yes, chose the way I did because I was striving for simplicity. On the other hand enums can offer more flexibility, since they can contain code. So I guess I will just move the tags into them.

    Anyway, will have to play around a little to see if this works.

    EDIT2:

    Figured out how to do what I wanted with enums. Only issue is... it is not very type safe. This is the enum:
    public enum Test
    {
    	ONE {
    		@Override
    		public String value()
    		{
    			return "One111";
    		}
    	},
    	TWO {
    		@Override
    		public Float value()
    		{
    			return 2.2f;
    		}
    	},
    	THREE {
    		@Override
    		public Integer value()
    		{
    			return 33;
    		}
    	};
     
    	public abstract <T> T value();
    }

    And this is the code that shows what the issues are:
    public class Program
    {
    	/**
    	 * @param args
    	 */
    	public static void main(String[] args) throws Exception
    	{
    		String s = Test.ONE.value();
    		System.out.println( s );
     
    		Float f = Test.TWO.value();
    		System.out.println( f );
     
    		Float invalid = Test.THREE.value(); // Causes a ClassCastException to be thrown
    		System.out.println( invalid );
    	}
    }
    There is not very much safety here, since this code that causes an error will compile. How would I solve this?
    Last edited by Kerr; May 24th, 2011 at 03:58 PM.

  4. #4
    Forum old-timer
    Join Date
    Nov 2008
    Location
    Faversham, Kent, UK
    Posts
    472
    My Mood
    Mellow
    Thanks
    4
    Thanked 58 Times in 54 Posts

    Default Re: Class hierarchy... giving me a headache, so I could use some help

    Quote Originally Posted by Kerr View Post
    The problem is that I would still have to make some casts, since I would have a list of all CPInfo objects (for example, one containing a float and another an int).
    Again, it depends what you want to do with these objects, how you want to use them. Without knowing that, I'm just guessing. The idea with generics and/or polymorphism is that you write the code so that you don't need to know the explicit types, and casting is not required. Also, with this particular example, the objects can tell you their type via the tag, so, if necessary, rather than casting, you can choose how to handle the object based on its tag. Alternatively, you could use a double-dispatch technique like the Visitor pattern. It all depends what your requirements are.

    However, this gives me an idea. Instead of having a class hierarchy I do it the other way around. Instead of posing as a base class, CPInfo could instead simply contain the tag stating what it is and then store the bytes. The other classes would then simply accept a CPInfo as a parameter to their constructor, and then interpret the bytes as they should do. That way I wouldnīt have to cast them.
    My first thought was that you just represent the structures described in the Constant Pool docs directly as classes. But, like I said, it depends on how you want to use them, and you haven't said.

    Figured out how to do what I wanted with enums. Only issue is... it is not very type safe. This is the enum:
    ...
    And this is the code that shows what the issues are:
    ...
    There is not very much safety here, since this code that causes an error will compile. How would I solve this?
    I really don't know, because I have no idea what you're trying to achieve.

  5. #5
    Member
    Join Date
    Mar 2011
    Location
    Earth!
    Posts
    77
    Thanks
    2
    Thanked 1 Time in 1 Post

    Default Re: Class hierarchy... giving me a headache, so I could use some help

    Now that is a good question. Have thought of it and realized I had focused on the wrong part. Basically I want to make a small program that can read a class file and the display data about it (like class name, methods, maybe even decompiled bytecode). It is so I can learn how the class format works and so. Think I will have to simply take a step back and try and look at the big picture (aka the entire application instead of a part of it) to get a good idea of how the best way to do this would be. Have done it a little and I am inclined to say that having a single class that simply stores the bytes may be better then having a class hierarchy and having to do a lot of casts, in this case. If you would like to continue to help me with that it would be welcome, but then it wouldnīt exactly fit in the "Object Oriented Programming" category.

    Sorry if I seem confused. My method of learning is to jump in head first and see what happens. Tend to make it a bit confusing, lol.

  6. #6
    Forum old-timer
    Join Date
    Nov 2008
    Location
    Faversham, Kent, UK
    Posts
    472
    My Mood
    Mellow
    Thanks
    4
    Thanked 58 Times in 54 Posts

    Default Re: Class hierarchy... giving me a headache, so I could use some help

    OK, if you just want to read and display data from a class file, you probably don't need any fancy class hierarchies, you can just follow the structures described in the docs. Once you have something basic that works, you'll probably see ways to simplify or enhance it. But remember that Donald Knuth said "We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil". See how you get on, and if you get any problems we'll probably still be around

  7. #7
    Member
    Join Date
    Mar 2011
    Location
    Earth!
    Posts
    77
    Thanks
    2
    Thanked 1 Time in 1 Post

    Default Re: Class hierarchy... giving me a headache, so I could use some help

    Sorry for the late response, but I think I have made it work now. Now I just need to figure out a good way to actually interpret the bytes and I am done with the constant pool (should be simple enough, will just make a class with just static methods that can read ints and such from byte arrays). Thanks for the help .

    And that quote is good to keep in mind. Didnīt even realize that was what I was doing xD.

Similar Threads

  1. A headache!
    By chrisivey1980 in forum What's Wrong With My Code?
    Replies: 9
    Last Post: May 24th, 2011, 08:48 AM
  2. [SOLVED] Giving Thread.sleep( ); a decimal value
    By Knox in forum Threads
    Replies: 2
    Last Post: April 9th, 2011, 08:55 PM
  3. JavaCompilerobject giving an error WITHOUT ide
    By divs1210 in forum What's Wrong With My Code?
    Replies: 1
    Last Post: April 2nd, 2011, 08:49 PM
  4. SAAJ giving exception with large attachments
    By Veronica in forum Web Frameworks
    Replies: 2
    Last Post: January 4th, 2011, 04:13 AM
  5. Vector Addition with small numbers giving NaN
    By Zula in forum What's Wrong With My Code?
    Replies: 4
    Last Post: October 28th, 2010, 09:29 PM