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

发布于 2024-08-16 22:58:25 字数 1607 浏览 4 评论 0原文

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

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 {};
}

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 {};
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

波浪屿的海角声 2024-08-23 22:58:25

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

这一切都在 Java 1.6 下进行。 但是正如其他人所指出的,我认为您对问题的诊断是错误的。

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

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

这样的构造会创建一个,用于例子。给出更多的代码,优秀的 SO 人员可能能够查明您的错误。

使用 javap 或更好的“真正的”Java 反汇编您的类文件可能会很有趣且有启发性像JD这样的反汇编程序。


更新

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

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

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

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.

放赐 2024-08-23 22:58:25

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

Java 枚举和附加类文件

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文