2013-07-26 9 views
5

Wenn ich kompilieren:Javac Behandlung static final anders basierend auf Zuweisungsverfahren

public static final boolean FOO = false; 
public static final void fooTest() { 
    if (FOO) { 
     System.out.println("gg"); 
    } 
} 

ich eine leere Methode fooTest() {} bekommen. Allerdings, wenn ich kompilieren:

static boolean isBar = false; 
public static final boolean BAR = isBar; 
public static final void fooTest() { 
    if (BAR) { 
     System.out.println("gg"); 
    } 
} 

die if-Anweisung in der kompilierten Klassendatei enthalten ist. Bedeutet das, dass es in Java zwei verschiedene "Arten" von statischen finalen gibt, oder ist das nur eine Compiler-Optimierung?

+5

Der Compiler kann Ausdrücke, die nur 'statische final'-Konstanten und Literalkonstanten enthalten, zur Kompilierzeit auswerten und bei Bedarf Optimierungen vornehmen. Der erste Ausdruck kann zur Kompilierzeit ausgewertet werden; das zweite kann nicht, weil es sich auf einen nicht endgültigen Ausdruck stützt. – dasblinkenlight

+2

Das bedeutet nicht, dass die JIT-Bytecode-Kompilierung es natürlich belassen wird. –

Antwort

7

Im ersten Fall führt der Compiler eine Optimierung durch. Es weiß Foo wird immer false sein und den Code töten, als nie erreicht werden wird.

Im zweiten Fall weisen Sie den Wert der nicht endgültigen Variable isBarBAR zu. Der Compiler kann nicht feststellen, ob die Variable isBar an anderer Stelle geändert wurde, insbesondere wenn sie nicht privat ist. Daher ist der Wert von BAR nicht sicher. Daher kann er die Optimierung nicht durchführen.

+1

Es ist nicht wirklich eine Compiler-Optimierung als solche. Dieses Verhalten wird von der Java-Sprachspezifikation benötigt. (* Kompilierzeitkonstante * ist die magische Phrase.) 'Privat' ist irrelevant - könnte in einer anderen Datei in einem anderen Paket enthalten sein, ohne auch nur den Quellcode zu haben. –

2

Im ersten Fall static final Felder sind Konstanten, die bei compile Zeit bekannt sind. So optimiert der Compiler und Inline die constant.

Im zweiten Fall ist das Feld non-finalvariable und kann nicht vom Compiler eingezeichnet werden, da es sich ändern kann.

class Test{ 
    public static final boolean BOOL = true; //CONSTANT KNOWN AT COMPILE TIME 


    public void someMethod(){ 
     while(BOOL){ 
      //some code 
     } 
    } 


    //OPTIMIZED VERSION DONE BY COMPILER 
    public void someMethod(){ 
     while(true){ //There is no need for accessing BOOL if it is not going to change and compiler understands that so inlines the value of constant 


     } 
    } 

} 

Sie an der kompilierte Code aussehen kann einige de-Compiler-Tools und Sie werden die optimierte Methode finden, die ich in der Klassendatei geschrieben.

2

Es ist ein reiner Fall von Compiler-Optimierung, wo es eine direkte Zuweisung ignoriert und indirekte Zuweisung von Literalen berücksichtigt.

0

Es könnte nur einen vorhandenen statischen Wert im Speicher geben. Im ersten Block wird die statische Endvariable FOO auf einen falschen Wert gesetzt, der dem Compiler bekannt ist und daher die if-Anweisung darin optimiert. Aber in der zweiten Anweisung wird die statische BAR statische Variable isBar statischen Variablenwert zugewiesen, was wiederum den Compiler dazu bringt, die if-Anweisung nicht zu optimieren (da isBar ein beliebiger Boolescher Wert sein kann und nicht bestimmt werden kann, da Java polymorphism unterstützt und Werte zugewiesen sind Variablen dynamisch während der Laufzeit.), daher statische Speicherposition im zweiten Block ist wichtig für den Compiler seinen Wert zu bestimmen, wobei wie im ersten Block der Wert falsch ohne Zuordnung zwischen verschiedenen Variablen bekannt ist und es optimiert ist.