12

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

整个 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 {};
}
4

2 回答 2

4

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

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

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

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

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

使用javap或更好的“真正的”Java 反汇编程序(如JD.


更新

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

您的代码当然是正确的(在我们可以看到的范围内),但设计不是很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 实现正在使用匿名类进行切换。蹩脚,但合法。
  2. 您有以下选择:
    • 消除switch
    • 使用不同的 Java 实现
    • 与匿名班级一起生活;抛弃make并使用antJava 的匿名类和其他奇怪之处。

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

于 2009-12-28T18:28:15.740 回答
3

确实似乎(至少在某些情况下)将为 switch 语句生成一个内部类:

Java 枚举和其他类文件

于 2009-12-28T21:03:59.133 回答