2

質問はJavaについてです。タイプのクラスを取得する方法は3つあります(コードはデモンストレーション用のスニペットのコレクションにすぎないことに注意してください)。

Class c1 = Class.forName("com.mypkg.MyClass"); //assumes initialize = true
// - OR - 
Class c1 = Class.forName("com.mypkg.MyClass", true/false,
                         this.getClass().getClassLoader());

Class c2 = com.mypkg.MyClass.class;
// - OR - 
import com.mypkg.MyClass;
Class c2 = MyClass.class;

MyClass mc = new MyClass();
Class c3 = mc.getClass();

私の質問は初期化についてです。メソッド1では、ブール引数を使用してクラスを初期化するかどうかを制御できます。メソッド3の場合、オブジェクトが作成されるため、明らかにクラスが初期化されます(右?)。

しかし、方法2はどうですか?.classクラスがまだ初期化されていない場合、呼び出しはクラスを初期化しますか?
そして、クラスがすでに初期化されているかどうかをプログラムで確認するにはどうすればよいでしょうか。

要約回答:

完全な回答については、受け入れられた解決策とそのコメントを参照してください。これは単なる要約です。

クラスがまだ初期化されていない場合、呼び出しはクラスを初期化.classしません。メッセージを出力するクラス定義の静的ブロックを使用して、クラスが初期化されているかどうかを確認できます。

元の質問の理由:

のjavadocによるとClass.forName「forName( "X")を呼び出すと、Xという名前のクラスが初期化されます。」。また、 initializeClass.forNameと呼ばれるブールパラメータを受け入れる方法を含む2つの方法があります。javadocによると、「クラスは、初期化パラメータがtrueであり、以前に初期化されていない場合にのみ初期化されます。」

4

2 に答える 2

6

VM の機能を確認するために、自分でテストしてみてはどうでしょうか。

このクラスを 3 つのメソッドすべてで使用するだけです (独立した実行では、初期化されるのはせいぜい 1 回だけです!)

class Example {
    static {
        System.out.println("Class was initialized!");
    }

    public static int bananas = 0;
}

クラスがいつ初期化されるかの詳細については、http://docs.oracle.com/javase/specs/#12.4.1 を参照しください

大まかに言えば、クラスは次のいずれかの場合に初期化されるはずです

  • 最初のインスタンスが作成されます
  • staticメソッドが呼び出される
  • 非最終staticフィールドが使用されています
  • いくつかのより複雑なコーナーケース

基本的に、実際のクラスの何かを最初に使用するときは、それを参照するだけではありません。

ただし、たとえばExample.bananas = 1;、インスタンスを持たずにクラスの初期化もトリガーする必要があります。

于 2012-12-06T08:45:02.227 に答える
1

バイトコードレベルでは、クラスへの参照はldc命令の1つによってロードされます。VM仕様では、クラスが初期化されるとは言及されていないため、おそらくVMはそのような参照がクラスを初期化することを保証しないということですが、VM仕様ではVMが初期化を行う必要がないことに注意してください。どちらか可能な限り怠惰に。

クラスは、最初に参照されてから初期化が厳密に要求されるまでの間、いつでも合法的に初期化できます。

于 2012-12-06T08:49:20.810 に答える