Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reference to Public Enum results in Anonymous Class

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 {};
}
like image 260
Maarx Avatar asked Dec 28 '09 18:12

Maarx


People also ask

Should enums be public or private?

Enum FieldsThe enum constructor must be private . You cannot use public or protected constructors for a Java enum .

Can we create an instance of enum outside of enum itself?

2. Can we create an instance of Enum outside of Enum itself? Explanation: No, instances of Enum cannot be created outside of Enum boundary, because Enum does not have a public constructor.

Can anonymous class have multiple methods?

Because the EventHandler<ActionEvent> interface contains only one method, you can use a lambda expression instead of an anonymous class expression. See the section Lambda Expressions for more information. Anonymous classes are ideal for implementing an interface that contains two or more methods.

What is the class that can represent an anonymous method?

In Java, a class can contain another class known as nested class. It's possible to create a nested class without giving any name. A nested class that doesn't have any name is known as an anonymous class. Anonymous classes usually extend subclasses or implement interfaces.


2 Answers

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.

like image 98
Carl Smotricz Avatar answered Oct 28 '22 14:10

Carl Smotricz


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

like image 42
2 revs Avatar answered Oct 28 '22 14:10

2 revs