2017-04-16 8 views
6
public class StaticTest { 

    private static String a; 
    private static String b = "this is " + a; 

    public static void main(String[] args) { 
     a = "test"; 

     System.out.println(b); // prints "this is null" 
    } 

} 

私は約bの値を混同しています。私は結果が "これはテスト"であるべきだと思いますが、結果は "これはヌル"です。どうして?このJava静的フィールドはなぜnullですか?

+8

クラスのロード時に静的フィールドが初期化されました。今のところ、「a」は「ヌル」だった。 – Oleksandr

答えて

4

文字列aを文字列bに追加しますが、文字列aはまだ定義されていません。定義した後、文字列bに追加する必要があります。

private static String a = "test"; 
private static String b = "this is a " + a; 
public static void main(String [] args){ 
    System.out.println(b); 
} 
+0

でも、変更があったら変更したいと思います。私はこの効果が欲しい。私は何をすべきか? – JianWan

2

あなたはanullた、この時点で

private static String a; 
private static String b = "this is " + a; 

をしました。したがって、Stringb今すぐ

this is null 

になった、aの変更はbに反映されないでしょう。したがって、この結果。期待される結果のためにdo

private String a = "test"; 
private String b = "this is " + a; 
6

他の人は、それがどのように動作するのか説明しました。

ただし、参照時に計算された値を持つ方法があります。あなたは値が算出されるbSupplier.get()を呼び出す

private static String a; 
private static Supplier<String> bSupplier =()->"this is " + a; 

public static void main(String[] args){ 
    a = "test"; 
    System.out.println(bSupplier.get()); //Prints "this is a test" 
} 

aの値を変更して再度呼び出すと、その値は新しい値を反映します。

これは頻繁に行うべきことではありませんが、知っておくと便利です。だから、

1

、あなたがプログラムを実行すると、あなたの主な方法は、それらが定義されているために、実行されているので、anullに設定されます、そしてb"this is null"に設定される前に、それらの静的フィールドが設定されている、アウトを開始するには、メインメソッドが実行され、aの値は"test"になります。

それは

private static String b = "this is" + a; 

を見たときにJavaがあるが"this is"を取り、その上にaを付けるん何。 aの値が後で変更された場合、bの値は無効になります。bには変数aへのリンクが格納されていないため、割り当てられた値が格納されます。

3

変更があった場合は変更したいと思います。私はこの効果が欲しい。 はどうすればよいですか?

スタティックフィールドは、クラスのロード時に初期化されます。
このクラスのメソッドでは、初期化中にこのフィールドを評価するために使用される変数の値を変更するだけで、静的フィールドの内容を変更することはできません。

あなたのケースでは、静的フィールドをbに使用しても、あなたのニーズには対応していません。
bそれが呼び出された時点での現在のa値に応じStringインスタンスを返す静的メソッドgetB()むしろ次のようになります。

public class StaticTest { 

    private static String a; 

    public static void main(String[] args) { 
     a = "test";  
     System.out.println(getB()); 
    } 

    private static String getB(){ 
     return "this is " + a;  
    } 
} 

PS:それはスティーブン・ローズの答えから近い十分な方法であることクラスローダは、JVMにクラスをロードするとき

+0

私たちは参考のように、追加することはできませんか?つまり、 '+'や '.concat'は、' String'の最後に 'chars'をコピーするだけです。おそらく 'StringBuilder'の参照を添付し、その内容を変更して、文字列' String'の変更を見たい場合はどうでしょうか?それは可能ですか? –

+0

良い、私はこれが好きです。ありがとうございました。 – JianWan

+0

@Shashwat文字列は不変です。 'StringBuilder'に追加された' String'は他の 'String'インスタンスに対して副作用を持つことはできません。 – davidxxx

1

のJava 8に特異的であり、それは三相

1)負荷

2)リンク (さらに3つの段階に分けて (IE)(B。)、検証の準備、(C)の決意)

3)だから、中に準備

を初期化します(リンク)フェーズ・クラス・ローダーは、スタティック変数(インスタンスではない)を初期化し、それらをデフォルトの初期値(実際の値ではない)に設定し、ストリングに対してはヌルです。

初期化フェーズでは、静的変数に実際の値が割り当てられますが、anullです。このステップの後にmainメソッドが実行されるためです。

Soはメインa内の値"test"割り当てられ、aがnullだったときには、文字列bは奇妙な出力を持っている理由があるので、bはすでに、初期化時にクラスローダによって割り当てられます。

関連する問題