Results 1 to 11 of 11
  1. #1
    IfElse is offline Member
    Join Date
    Feb 2011
    Posts
    6
    Rep Power
    0

    Default compiling with Enum

    I don't understand something the compiler is doing with the following class file (reduced to the bare essentials for this question):

    Java Code:
    enum State {One, Two}
    
    class Test {	
         void stateTest(State s) {
              switch(s) {
                   case One: break;
                   case Two: break;
              }
         }
    }
    It creates three class files: State.class, Test.class, and Test$1.class. Why the anonymous inner class Test$1.class?

    The funny thing is if I remove the switch() statement and replace it with a println() call, I don't get the Test$1.class generated anymore.

  2. #2
    IfElse is offline Member
    Join Date
    Feb 2011
    Posts
    6
    Rep Power
    0

    Default

    I've created a more detailed example to show just how strange this looks:

    Java Code:
    enum State {One, Two}
    
    class TestOne {	
         void stateTest(State s) {
              switch(s) {
                   case One: break;
                   case Two: break;
              }
         }
    }
    class TestTwo {
         void stateTest(State s) {
              System.out.println("TestTwo");
         }
    }
    
    class TestThree {	
         void stateTest(int s) {
              switch(s) {
                   case 1: break;
                   case 2: break;
              }
         }
    }
    If you compile this code you will find the following class files:
    State.class
    TestOne.class
    TestOne$1.class
    TestTwo.class
    TestThree.class

    So it appears that the combination of using an enum in a switch causes the extra class to be generated? Why??

    This isn't just academic- it's reduced from a real program. In the original code there are method calls inside the switch that use "this" as a parameter. By experimenting a bit I found that the "this" that's used within the switch is in fact the inner class TestOne$.class.

    My program works but I don't want to go much further until I understand this strange compiling effect.

    Even if you can't explain it, I hope someone will verify that this is in fact happening. I've checked it dozens of times, but I am new to Java, so maybe I'm making some newbie error.

  3. #3
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,316
    Blog Entries
    1
    Rep Power
    26

    Default

    When compiling this code, I'm not getting the extra inner class (TestOne$1.class) that you're seeing, so I can't explain it or reproduce it. Sorry.

  4. #4
    IfElse is offline Member
    Join Date
    Feb 2011
    Posts
    6
    Rep Power
    0

    Default

    Thank you for testing it.

    I wonder if you could help me figure out why I'm getting that extra class file. I'm using the jre6 and jdk1.6.0_23 on a Windows 7 PC.

    I really am getting that file. I copied and pasted from my own post, and compiled in a brand new directory, just to make sure. In the original program when I removed the extra $1.class file, the program exited with a Class Not Found (or some such) error. That's how I was able to trace it down to this switch() statement.

    Any ideas at all??

  5. #5
    toadaly is offline Senior Member
    Join Date
    Jan 2009
    Posts
    671
    Rep Power
    6

    Default

    The files that are produced by the compiler are up to the compiler implementation. The only restrictions the spec implies (IIRC) is that an outer class produce at least 1 class file by the same name as that class.

    You're worrying about something you shouldn't care about. If you really just feel like you must know what's going on inside the compiler, you'll need to obtain source code for the particular compiler you're using, or ask one of the developers who wrote it.

  6. #6
    IfElse is offline Member
    Join Date
    Feb 2011
    Posts
    6
    Rep Power
    0

    Default

    Quote Originally Posted by toadaly View Post
    The files that are produced by the compiler are up to the compiler implementation. The only restrictions the spec implies (IIRC) is that an outer class produce at least 1 class file by the same name as that class.

    You're worrying about something you shouldn't care about. If you really just feel like you must know what's going on inside the compiler, you'll need to obtain source code for the particular compiler you're using, or ask one of the developers who wrote it.
    OK, that's helpful. I was thinking the classes created were part of the language spec, and only the naming of them was left to the compiler.

    Still seems odd, but now I'll just chalk it up to the implementation of the jdk.

    Thanks for answering.

  7. #7
    JosAH's Avatar
    JosAH is offline Moderator
    Join Date
    Sep 2008
    Location
    Voorschoten, the Netherlands
    Posts
    13,310
    Blog Entries
    7
    Rep Power
    20

    Default

    Interesting; I don't get that anonymous class either; I'm using Java 1.6.0.20; which version are you using?

    kind regards,

    Jos
    cenosillicaphobia: the fear for an empty beer glass

  8. #8
    j2me64's Avatar
    j2me64 is offline Senior Member
    Join Date
    Sep 2009
    Location
    Zurich, Switzerland
    Posts
    962
    Rep Power
    5

    Default

    Quote Originally Posted by Fubarable View Post
    When compiling this code, I'm not getting the extra inner class (TestOne$1.class) that you're seeing, so I can't explain it or reproduce it. Sorry.

    when i first compile it inside eclipse i got two classes State and Test, but compiling the code with javac i got a file Test$1.class. so i was also wandering about the content and decompiling it i got this code

    Java Code:
    // Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov.
    // Jad home page: http://www.kpdus.com/jad.html
    // Decompiler options: packimports(3) 
    // Source File Name:   Test.java
    
    // Referenced classes of package myclass:
    //            Test, State
    
    static class Test$1
    {
    
        static final int $SwitchMap$myclass$State[];
    
        static 
        {
            $SwitchMap$myclass$State = new int[State.values().length];
            try
            {
                $SwitchMap$myclass$State[State.One.ordinal()] = 1;
            }
            catch(NoSuchFieldError nosuchfielderror) { }
            try
            {
                $SwitchMap$myclass$State[State.Two.ordinal()] = 2;
            }
            catch(NoSuchFieldError nosuchfielderror1) { }
        }
    }

    the code looks like an implementation of the enum State at a lower level.
    Last edited by j2me64; 02-14-2011 at 06:49 PM.

  9. #9
    pbrockway2 is offline Moderator
    Join Date
    Feb 2009
    Location
    New Zealand
    Posts
    4,565
    Rep Power
    12

    Default

    fwiw I do see the $1 class using 1.6.0_20 - so you're not seeing things! (Or we both are...)

    I can't imagine how this would end up as a reference to an instance of Test$1 though.

  10. #10
    JosAH's Avatar
    JosAH is offline Moderator
    Join Date
    Sep 2008
    Location
    Voorschoten, the Netherlands
    Posts
    13,310
    Blog Entries
    7
    Rep Power
    20

    Default

    Quote Originally Posted by pbrockway2 View Post
    fwiw I do see the $1 class using 1.6.0_20 - so you're not seeing things! (Or we both are...)

    I can't imagine how this would end up as a reference to an instance of Test$1 though.
    I plea incompetence your honour; I compiled it with Eclipse's compiler and it doesn't generate an anonymous class file; j2me64 is right: javac does generate it.

    kind regards,

    Jos
    cenosillicaphobia: the fear for an empty beer glass

  11. #11
    IfElse is offline Member
    Join Date
    Feb 2011
    Posts
    6
    Rep Power
    0

    Default

    Thanks everyone for looking into this some more.


    Quote Originally Posted by pbrockway2 View Post
    fwiw I do see the $1 class using 1.6.0_20 - so you're not seeing things! (Or we both are...)

    I can't imagine how this would end up as a reference to an instance of Test$1 though.

    I was mistaken about this. I came to that conclusion after running javap on TestClass and TestClass$1. But I'm in Windows on the command line, so the results were identical. Ergo, TestOne$1.class is another version of TestOne.class. D'oh!

    Running javap on TestOne and 'TestOne$1' here's what I get:

    javap TestOne

    Compiled from "State.java"
    class TestOne extends java.lang.Object {
    TestOne();
    void stateTest(State);
    }

    javap 'TestOne$1'

    Compiled from "State.java"
    class TestOne$1 extends java.lang.Object {
    static final int $SwitchMap$State$;
    static {}
    }

    Which gives the same conclusion as j2me64 that it's another version of State. Perhaps it's useful for enums inside switch statements somehow.
    Last edited by IfElse; 02-16-2011 at 07:14 PM. Reason: add comment

Similar Threads

  1. Setting values from One Enum type to another enum type.
    By reach2sudhakar in forum New To Java
    Replies: 3
    Last Post: 09-23-2010, 06:02 PM
  2. enum
    By billq in forum New To Java
    Replies: 3
    Last Post: 01-03-2010, 08:38 PM
  3. Enum example
    By Java Tip in forum java.lang
    Replies: 0
    Last Post: 04-17-2008, 07:34 PM
  4. How to use enum
    By Java Tip in forum java.lang
    Replies: 0
    Last Post: 04-17-2008, 07:34 PM
  5. Enum?
    By vgbhagavan in forum Advanced Java
    Replies: 0
    Last Post: 06-14-2007, 02:02 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •