18

たまたま職場で Java コードに出くわしました。シナリオは次のとおりです。 と の 2 つのクラスがありClassAますClassB

ClassA内部には 4 つの public static final 文字列値以外は何もありません。その目的は、これらの値を次のように使用することですClassA.variable(理由は聞かないでください。これは私のコードではありません)。

ClassB輸入品ClassA。文字列値を編集しClassAてコンパイルしました。実行するとClassB、新しい値ではなく、古い値が使用されていることがわかりました。ClassBからの新しい値を使用するように再コンパイルする必要がありましたClassA。(インポートする他のクラスを再コンパイルする必要がありましたClassA!)

これは単に JDK 1.6 のせいなのか、それとも以前に再コンパイルすることを知っていたはずClassBです! 私を啓発します。:)

4

5 に答える 5

23

finalクラスからの変数の値がClassAたまたまコンパイル時の定数である場合、コンパイラはClassA実行時の参照を生成する代わりに、を使用してそれらをクラスにインライン化した可能性があります。あなたが説明したケースでは、これが起こったと思います。

例:

public class Flags {
    public static final int FOO = 1;
    public static final int BAR = 2;
}

public class Consumer {
    public static void main(String[] args) {
         System.out.println(Flags.FOO);
    }
}

この例では、コンパイラは同等の実行時参照を生成する代わりに、FOO生成されたコードにの値を組み込む可能性があります。Consumerの値が後で変更された場合は、新しい値を使用するためにFOO再コンパイルする必要があります。Consumer

これは最適化であり、コンパイルされたプログラムの効率と速度に関していくつかの利点があります。たとえば、値をインライン化すると、それを使用する式でさらに最適化できる場合があります。次に例を示します。

int x = Flags.FOO * 10;

この例では、値 (ここでは 1) をインライン化することで、コンパイラは、乗算に違いはなく、すべて省略できることに気付くことができます。

于 2009-11-07T14:10:49.627 に答える
3

ClassA が次のようになっているとします。

public class ClassA {
    public static final int FOO = 1;
    public static final int BAR = 2;
}

再コンパイルすると、ClassB は古い値を使用し続けます。コンパイラにもよると思いますが、これが典型的な動作だと思います。ClassA の定数が変更されるたびに ClassB を再コンパイルしたくない場合は、次のようにする必要があります。

public class ClassA {
    public static final int FOO = CONST(1);
    public static final int BAR = CONST(2);

    public static int CONST(int i) { return i; }
}

現在、javac は定数をインライン化することを望まないためです。代わりに、ClassA の静的初期化子の実行時に CONST(int) メソッドを呼び出します。

于 2012-08-22T01:45:10.533 に答える
2

クラスを個別にコンパイルしようとしているのはなぜですか?

maven や ant などのビルド システムを使用するか、IDE に任せてください。

唯一の安全な方法は、影響を受ける可能性のあるすべてのクラスが再コンパイルされるまで、変更された Java クラスに依存するすべての Java を再コンパイルすることです。

于 2009-11-07T15:37:35.243 に答える