对公共枚举的引用导致匿名类

时间:2009-12-28 18:02:31

标签: java switch-statement enums anonymous anonymous-class

我在编译时得到一个我没想到的匿名类。相关代码如下,然后是更详细的解释:

CircuitType.java的整体:

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

来自Auditor.java,第3-9行:

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

来自Auditor.java,第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;
}
[...]

来自Circuit.java,第1-5行:

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

当命令

javac *.java
执行

,生成一个匿名类Auditor $ 1.java。显然,这些文件在一个不包含其他内容的文件系统目录中彼此相邻。

当第104-121行被注释掉时,不会生成任何匿名类。

我起初认为这是一个包问题,所以把这三个类放在一个包中,但我对包没有足够的了解才能使它正常工作。如果它确实是一个包问题,有人可以指导我完全如何标记它们吗?不过,如果我不需要,我宁愿不打包它们。

匿名类是一个问题的原因,除了这些类通常表示命名空间问题的事实是它打破了我用于自动编译的Makefile。

更新


附件是一个控制台会议,我希望可以阐明这个谜团:

% javap 'Auditor$1'
Compiled from "Auditor.java"
class Auditor$1 extends java.lang.Object{
    static final int[] $SwitchMap$CircuitType;
    static {};
}

2 个答案:

答案 0 :(得分:4)

我已经开始构建了一个包含你发布的源代码的小项目,并且只有足够的框架来编译它。我有3个类文件:Circuit.class,CircuitType.class和Auditor.class - 正如预期的那样。

所有这些都在Java 1.6下。 但正如其他人所说,我认为你对这个问题的诊断是关闭的。

匿名类很容易意外生成:通常是像

这样的结构
Circuit myCircuit = new Circuit() {
   public CircuitType getCircuitType() {
      return XXX;
   }
}
例如,

将创建一个。鉴于您的代码更多,优秀的SO人员可能能够找出您的错误。

使用javap或更好的“真实”Java反汇编程序(如JD)反汇编类文件可能会很有趣,也很有启发性。


<强>更新

将我的新审核员代码添加到我的...没有变化。没有匿名课程。

您的代码当然是正确的(我们可以看到它),但设计不是很好。有些人会指出,每次出现新电路类型时,您都必须扩展计数器声明和switch语句。

你也没有充分利用枚举的“特殊功能”。我有一个简化版的Auditor方法:

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

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

更新2

我发现你的javap输出很有启发性。请参阅下面的评论。

我的结论:

  1. 是的,显然你的Java impl正在为交换机使用anon类。瘸子,但合法。
  2. 您有以下选择:
    • 消除switch
    • 使用不同的Java实现
    • 和匿名班一起生活;抛弃make并使用ant来接受Java的匿名类和其他异常。
  3. 由于您的非标准编译设置只会出现问题,我会选择最后一个解决方案并解决问题。

答案 1 :(得分:3)

确实会出现(至少在某些情况下)将为switch语句生成内部类:

Java enum and additional class files