2017-04-16 4 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" 
    } 

} 

Ich bin verwirrt über b Wert. Ich denke, das Ergebnis sollte "das ist Test" sein, aber das Ergebnis ist "das ist Null". Warum?Warum ist dieses statische Java-Feld null?

+8

Statisches Feld wurde während der Klassenlast initialisiert. In diesem Moment war 'a'' null'. – Oleksandr

Antwort

4

Sie fügen String a zu String b hinzu, aber String a ist noch nicht definiert. Sie sollten ihn zu String b hinzufügen, nachdem Sie ihn definiert haben.

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

aber ich wünsche Wechsel b wenn sich ändert. Ich möchte diesen Effekt. Was soll ich machen? – JianWan

2

Sie

tat An diesem Punkt
private static String a; 
private static String b = "this is " + a; 

war anull. Daher wurde die Stringb

this is null 

Jetzt, werden alle Änderungen in a nicht auf b widerspiegeln würde. Daher dieses Ergebnis. Für das erwartete Ergebnis tun Sie

6

Andere haben erklärt, warum es so funktioniert, wie es tut.

Es gibt jedoch Möglichkeiten, den Wert zu berechnen, wenn Sie ihn referenzieren.

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" 
} 

Wenn Sie bSupplier.get() der Wert nennen berechnet. Wenn Sie den Wert a ändern und es erneut aufrufen, spiegelt der Wert den neuen Wert wider.

Dies ist nicht etwas, was Sie oft tun sollten, aber es ist nützlich zu wissen.

1

Also, zu beginnen, wenn Sie Ihr Programm ausführen, wird diese statischen Felder festgelegt werden, bevor der Hauptmechanismus läuft, in der Reihenfolge, in der sie definiert ist, so a zu null gesetzt wird, und b-"this is null" gesetzt wird, und dann wird Ihre Hauptmethode ausgeführt, die a einen Wert von "test" hat.

Was Java tut, wenn es

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

Is "this is" nimmt und legt den Wert von a auf sie. Wenn sich der Wert von a später ändert, wird der Wert b nicht angezeigt, da b keine Verknüpfung zur Variablen a speichert, sondern nur den zugewiesenen Wert.

3

aber ich wünsche Wechsel b, wenn sich ändert. Ich möchte diesen Effekt. Was soll ich tun ?

Statische Felder werden initialisiert, wenn die Klasse geladen wird.
So können Sie in einer Methode der Klasse den Inhalt des statischen Felds nicht ändern, indem Sie einfach den Wert einer der Variablen ändern, die während der Initialisierung dieses Felds verwendet werden.

In Ihrem Fall mit statischen Feld für b nicht Ihren Bedarf.
b sollte eher eine statische Methode sein getB(), die eine String Instanz zurückgibt nach dem aktuellen a Wert zu dem Zeitpunkt, wo sie aufgerufen wird:

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: Es ist ein nahe genug Weg aus der Antwort Steven Lowes ist das ist spezifisch für Java 8.

+0

können wir nicht anhängen, mit einer Referenz? Ich meine, für jetzt verstehe ich, dass "+" oder ".concat", nur "Zeichen" am Ende der "Zeichenfolge" kopiert. Was ist, wenn wir eine Referenz, möglicherweise von 'StringBuilder', anhängen und dann seinen Inhalt mutieren und die Änderung im orignal' String' sehen wollen. Ist das möglich ? –

+0

gut, das gefällt mir. Vielen Dank. – JianWan

+0

@Shashwat Strings sind unveränderlich. Jede an den 'StringBuilder' angefügte 'Zeichenfolge' kann keine Nebenwirkung auf andere' String'-Instanzen haben. – davidxxx

1

Wenn Classloader eine Klasse in JVM lädt, macht es es in drei Phasen

1.) Legen sie

2.) Link- (die weiter in drei Stufen unterteilt ist, dh (a.) Überprüfen, (b.) Vorzubereiten, (c.) Resolve)

3.) Initialisieren

So während vorbereiten (Link) phase classloader initialisiert die statischen Variablen (nicht Instanz) und setzt sie auf ihre Standardwerte (nicht den tatsächlichen Wert) und für die Zeichenkette ist es null.

Jetzt Während der Initialize-Phase wird den statischen Variablen ihr tatsächlicher Wert zugewiesen und immer noch a ist null. Weil nach diesem Schritt main Methode ausgeführt wird.

So innen Haupt a wird Wert zugewiesen "test" und b wird bereits von Classloader bei der Initialisierung zugewiesen wird, wenn a null war, so dass ist der Grund, String b seltsamen Ausgang.