13

I'm getting an anonymous class at compile-time that I'm not expecting. Relevant code follows, then a more detailed explanation:

Entirety of CircuitType.java:

public enum CircuitType { V110A20, V110A30, V208A20, V208A30 }

From Auditor.java, lines 3-9:

public class Auditor {
    private String[] fileNames;
    private int numV110A20;
    private int numV110A30;
    private int numV208A20;
    private int numV208A30;

From Auditor.java, lines 104-121:

[...]
switch (newCircuit.getType()) {
    case V110A20:
        this.numV110A20++;
        break;
    case V110A30:
        this.numV110A30++;
        break;
    case V208A20:
        this.numV208A20++;
        break;
    case V208A30:
        this.numV208A30++;
        break;
    default:
        System.err.println("An Error Has Occured.");
        System.exit(-1);
        break;
}
[...]

From Circuit.java, lines 1-5:

public class Circuit {
    private CircuitType myType;
    public CircuitType getType() {
        return this.myType;
    }
[...]

When the command

javac *.java

is executed, an anonymous class Auditor$1.java is generated. The files, obviously, all sit next to each other in a file system directory that contains nothing else.

When lines 104-121 are commented out, no anonymous class is generated.

I at first thought it was a package issue, so put the three classes in a package, but I didn't know enough about packages to get it working. If it's truely a package issue, can someone step me through exactly how to label them? I'd rather not have to package them if I don't have to, though.

The reason the anonymous class is a problem, besides the fact that such classes usually signify a namespace issue, is that it breaks my Makefile I use for automatic compilation.

Update


Attached is a console session which I hope may shed light on this mystery:

% javap 'Auditor$1'
Compiled from "Auditor.java"
class Auditor$1 extends java.lang.Object{
    static final int[] $SwitchMap$CircuitType;
    static {};
}
Maarx
  • 633
  • 1
  • 7
  • 18
  • 1
    Unfortunately I can't help with the problem, but +1 posting a very well stated question. – Topher Fangio Dec 28 '09 at 18:06
  • 1
    This is probably not the answer you wanted to hear, but `make` is not really a suitable tool for Java development. I strongly recommend using `ant` instead. As you develop more complex applications, you will have anonymous classes all over the place, and rightly so. – Carl Smotricz Dec 28 '09 at 18:16
  • I'd be interested to see more of Auditor.java. Based on what you've stated here I find it hard to believe that Circuit.java is the issue. – Shaun Dec 28 '09 at 18:16
  • I included more of Auditor.java, per your request. – Maarx Dec 28 '09 at 18:28
  • StackOverflow would probably not explode if you posted your complete code. On the other hand, you're welcome to e-mail me your code. myFirstName.myLastName@gmail.com . – Carl Smotricz Dec 28 '09 at 19:37
  • @Carl: I would love to, however, it is company property (although I am the sole author). I've pushed the envelope about as far as I dare already. – Maarx Dec 28 '09 at 19:53
  • Updated my answer and added a new comment. – Carl Smotricz Dec 28 '09 at 20:54
  • possible duplicate of http://stackoverflow.com/questions/1834632/java-enum-and-additional-class-files – Brad Cupit Feb 09 '12 at 17:11

2 Answers2

4

I've gone ahead and built a little project containing the source you posted and just enough framework around it to make it compile. I got 3 class files: Circuit.class, CircuitType.class and Auditor.class - as expected.

All this under Java 1.6. But as others have indicated, I think your diagnosis of the problem is off.

Anonymous classes are easy to generate accidentally: Typically a construct like

Circuit myCircuit = new Circuit() {
   public CircuitType getCircuitType() {
      return XXX;
   }
}

will create one, for example. Given more of your code, the good SO folks might be able to pinpoint your error.

It might be interesting and instructive to disassemble your class files with javap or better yet a "real" Java disassembler like JD.


Update

Added your new Auditor code to mine... no change. No anonymous classes.

Your code is of course correct (to the extent we can see it) but the design is not very OO. Some people would point out that you'll have to extend your counter declarations and your switch statement every time a new circuit type appears.

You're also not making much use of the "special features" of enums. I have a much simplified version of your Auditor method:

   private int[] counters = new int[CircuitType.values().length];

   public void tallySomething() {
      Circuit newCircuit = new Circuit();
      counters[newCircuit.getType().ordinal()]++;
  }

Update 2

I found your javap output quite illuminating. See my comment below.

My conclusions:

  1. Yes, apparently your Java impl is using an anon class for the switch. Lame, but legitimate.
  2. You have the following options:
    • eliminate the switch
    • use a different Java implementation
    • live with the anonymous class; ditch make and use ant to embrace the anon classes and other strangenesses of Java.

Since you're only having problems because of your non-standard compilation setup, I'd go with the last solution and attack the problem there.

Carl Smotricz
  • 66,391
  • 18
  • 125
  • 167
  • I included more code from Auditor.java, per your request. The line 104-121 code block is for-sure the culprit, as the anonymous class is not generated when that code block is commented out. I believe I've included everything relevant to that code block. If you need anything else, please let me know. – Maarx Dec 28 '09 at 18:41
  • My mind is blown. Twice. There is definitely an anonymous class for me with the switch statement, and there is definitely no anonymous class when the switch statement is commented out. When you said you still didn't get an anonymous class, I moved the code from my UNIX development environment to a throw-away Windows virtual machine with the latest JDK update and recompiled. I still get an anonymous class with the switch statement, and none without. – Maarx Dec 28 '09 at 18:57
  • Your method of tallying was also a surprise. I am rewriting my switch with your method, both because it's better and to see if maybe it resolves the anonymous class issue. – Maarx Dec 28 '09 at 18:58
  • @Carl: I have updated my question with the output of 'javap'. While I've never used 'javap' before and didn't even know about it until you mentioned it, the output seems rather definitively involved with the nature of the switch statement. However, I cannot divine anything further. Perhaps you can? – Maarx Dec 28 '09 at 19:52
  • 1
    Yes... the javap is indeed interesting. Apparently your particular Java implementation uses this anonymous class to implement the switch-on-enum feature. Thing to realize is, the java `switch` statement really only 'does' `int`s. Most of these cool new language features are just syntactic sugar on "basic" Java. Seems the switch statement is implemented by looking up the enum in a map and then switching on the int stored as the value. – Carl Smotricz Dec 28 '09 at 20:48
  • Out of curiosity, what java implementation are you using that DOESN'T make an anonymous class for the switch? I'd think installing the most recent JDK right off Sun's website onto a pre-built HP Compaq Core2 vPro running Windows Vista is about as standard an implementation as you could get, and I still got an anonymous class. – Maarx Dec 29 '09 at 23:23
  • I'm doing most of my Java work using the Eclipse IDE. Some other people have mentioned that this problem doesn't happen with Eclipse. As far as I know there's an IBM compiler built into Eclipse to do the incremental compilation thing. It kinda sidesteps the installed compiler, I think. The compiler is very good; in this particular case, apparently better than the standard :) – Carl Smotricz Dec 30 '09 at 01:05
4

It indeed appears that (in certain cases at least) an inner class will be generated for the switch statement:

Java enum and additional class files

Community
  • 1
  • 1
ZoogieZork
  • 11,215
  • 5
  • 45
  • 42