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がコメント化されている場合、匿名クラスは生成されません。

最初はパッケージの問題だと思っていたので、3つのクラスをパッケージに入れましたが、パッケージを機能させるには十分な知識がありませんでした。それが本当にパッケージの問題である場合、誰かがそれらにラベルを付ける方法を正確に説明できますか?ただし、必要がなければ、パッケージ化する必要はありません。

匿名クラスが問題になる理由は、そのようなクラスが通常名前空間の問題を意味するという事実に加えて、自動コンパイルに使用する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

私は先に進み、あなたが投稿したソースと、それをコンパイルするのに十分なフレームワークを含む小さなプロジェクトを構築しました。予想通り、Circuit.class、CircuitType.class、Auditor.class の 3 つのクラス ファイルを取得しました。

これはすべて Java 1.6 で行われます。しかし、他の人が指摘したように、問題の診断は間違っていると思います。

匿名クラスは誤って簡単に生成されます: 通常、次のような構造

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

たとえば、作成します。より多くのコードがあれば、善良な SO 関係者がエラーを特定できる可能性があります。

javapのような「実際の」Java 逆アセンブラーを使用してクラス ファイルを逆アセンブルすることは、興味深く有益な場合がありJDます。


アップデート

あなたの新しい Auditor コードを私のものに追加しました...変更はありません。匿名クラスはありません。

もちろん、あなたのコードは(私たちが見る限り)正しいですが、デザインはあまりオブジェクト指向ではありません。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 クラスやその他の奇妙さを受け入れるためには、捨てmakeて使用してください。ant

非標準のコンパイル設定が原因で問題が発生しているだけなので、最後の解決策を使用して、そこで問題を攻撃します。

于 2009-12-28T18:28:15.740 に答える
3

実際、(少なくとも特定のケースでは) switch ステートメントに対して内部クラスが生成されるようです。

Java 列挙型と追加のクラス ファイル

于 2009-12-28T21:03:59.133 に答える