1

次のシナリオ パッケージ com.example.test; があります。

public class StaticTest {

    public static final String STATIC_VAR="Static Var";

    static{
        System.out.println("Static Block Called....");
    }
public static void init(){}
}

package com.example.test;

public class MainClass {
    public static void main(String[] args) {
        System.out.println("Test static initialization");
        String staticvar =StaticTest.STATIC_VAR;
        System.out.println("Referred static variable--> "+ staticvar);
        System.out.println("Calling static method");
        StaticTest.init();
        System.out.println("Static method invoked");
    }

}

私が得ている出力は

Test static initialization
Referred static variable--> Static Var
Calling static method
**Static Block Called....**
Static method invoked

そして、私が期待していた出力は

Test static initialization
**Static Block Called....**
Referred static variable--> Static Var
Calling static method
Static method invoked

静的変数を参照するとすぐに静的ブロックが実行されると考えていました。

説明はありますか?

4

3 に答える 3

3
String staticvar =StaticTest.STATIC_VAR; 

クラスをロードしませんStaticTest。代わりに、コンパイラは定数の値を にインライン化します。したがって、実行時に次のコードが実行されます。MainClass

String staticvar = "Static Var"; 

JLS はこれを「定数」と呼んでいます。

final であり、コンパイル時の定数式 (§15.28) で初期化されるプリミティブ型または型 String の変数は、定数変数と呼ばれます。

つまりStaticTest.init();、VM が実際にクラスをロードする必要があるのは初めてです。これにより、静的ブロックが実行されます。

于 2013-04-12T07:54:20.730 に答える
3

変数はpublic static finalコンパイラによってインライン化されているためです。

それへのすべての参照は、変更できないため、実際の値に置き換えられます。これは、コンパイル時定数として知られています。

コードは基本的に次のようにコンパイルされています。

System.out.println("Test static initialization");
String staticvar = "Static Var";

メソッドの戻り値に値を代入する場合 -

public static final String STATIC_VAR=getStaticVar();
private static String getStaticVar() {
    return "Static Var";
}

期待どおりの結果が得られます。

インライン展開と、コンパイル時定数に関する JLS によって与えられる保証について説明しているSOの良い回答があります。

于 2013-04-12T07:55:49.157 に答える
0

主な理由は、STATIC_VAR参照される代わりにコンパイラによってインライン化される定数値として宣言したことです。コードを次のように変更します

public static /*final*/ String STATIC_VAR="Static Var";

期待どおりの動作が得られます。

§12.4.1を参照してください。Java言語仕様の初期化が発生した場合:

クラスまたはインターフェイスの型 T は、次のいずれかが最初に発生する直前に初期化されます。

  • ...
  • T によって宣言された静的フィールドが使用され、そのフィールドは定数変数ではありません (§4.12.4)。

inlining技術的な背景については、定数値に関する他の回答を参照してください。

于 2013-04-12T07:59:20.757 に答える