对匿名类中公共枚举结果的引用

我在编译时得到了一个我意想不到的匿名类。相关代码如下,然后进行更详细的说明:

整个电路类型.java:

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

来自审计员.java,第3-9行:

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

来自审计员.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;
}
[...]

从电路.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 {};
}

答案 1

我已经继续构建了一个小项目,其中包含您发布的源代码以及足够的框架来使其编译。我得到了3个类文件:Circuit.class,CircuitType.class和Auditor.class - 如预期的那样。

所有这些都在Java 1.6下进行。但正如其他人所指出的那样,我认为你对这个问题的诊断是错误的。

匿名类很容易意外生成:通常是像这样的结构

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

例如,将创建一个。给定更多的代码,优秀的SO人员可能能够查明您的错误。

使用“真正的”Java反汇编器(如 .javapJD


更新

已将新的审计员代码添加到我的...无变化。没有匿名类。

你的代码当然是正确的(在我们看到的范围内),但设计不是很OO。有些人会指出,每次出现新的电路类型时,您都必须扩展计数器声明和语句。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 实现
    • 与匿名班级住在一起;抛弃并用于拥抱Java的anon类和其他奇怪之处。makeant

由于您只是因为非标准编译设置而遇到问题,因此我会使用最后一个解决方案并在那里解决问题。


答案 2

看起来(至少在某些情况下)将为 switch 语句生成一个内部类:

Java 枚举和其他类文件