16
public class Test {

    private static final String str1 = new String("en");
    private static Test instance = initInstance();

    private static final String str2 = new String("en");
    private static final String str3 = "en";

    private Test() {
    }

    public static void main(String[] args) {
    }

    private static Test initInstance() {
        instance = new Test();
        System.out.println(str1 + ',' + str2 + ',' + str3);
        return instance;
    }
}

理論的には、どこにでも静力学があると、「en、en、en」になるはずです。

結果: "en、null、en"

予想: "en、null、null"(静力学の順序が実際に重要であることがわかったため)

誰かがこれを説明できますか?"en"とnewString( "en")の違いは何ですか?

4

3 に答える 3

19

はい。メソッドを呼び出した時点では、str2はまだ初期化されておらず(フィールドは宣言順に初期化されています)、str3はコンパイル時定数です。

コンパイル時定数は、コンパイラによってクラスファイルにインライン化されます。new String( "..")はコンストラクターを使用するため、定数ではありません。

文字列定数は文字列リテラル""で定義され、jvmインスタンスの文字列プールに配置されて再利用されます。それとは逆に、new String(..)を使用すると新しいインスタンスが作成されるため、避ける必要があります。

于 2012-07-20T13:12:11.910 に答える
11

これは、定数で初期化されたクラス変数が最初に初期化され、次に、より複雑な初期化子(を使用する式などnew String())が実行されるために発生します(これらはソース順に実行されます)。JLS§8.3.2.1を参照してください。

8.3.2.1。クラス変数の初期化子

[...]

実行時に、定数式(§15.28)で初期化されたstaticフィールドが最初に初期化されます( §12.4.2)。これは、インターフェースのそのようなフィールドにも当てはまります(§9.3.1)。これらのフィールドは「定数」であり、不正なプログラム( §13.4.9 )によっても、デフォルトの初期値( §4.12.5 )を持つことは決してありません。final

于 2012-07-20T13:12:18.067 に答える
4

1.str3 = "en" is a String literal in literal pool, and str1 = new String("en") is a String object文字列オブジェクトプールにあるためです。

2.en」はリテラル、つまり「定数」であるため、最初に初期化されます

3.定数畳み込みとも呼ばれ、より高速に実行するための定数の事前計算。

于 2012-07-20T13:17:14.960 に答える