2014-10-07 9 views
22

Dieser Kommentar wurde in einem Code-Review verfasst und die Person, die ihn erstellt hat, gehört nicht mehr zu unserem Team.Deklaration der Variablen final und statisch

Jeder Typ, der vom Klassenlader zur Laufzeit aufgelöst werden muss, sollte niemals Instanzen enthalten, die von Referenzen gehalten werden, die sowohl als endgültig als auch als statisch deklariert sind.

Hier ist die Codezeile:

private final static Logger log = LoggerFactory.getLogger(MyClass.class); 

Ich bin vertraut mit der Debatte von Loggern statischen oder nicht-statischen deklarieren, aber dieser Kommentar scheint allgemeiner zu sein. Ich kann keine Erklärungen finden, warum statische und finale schlecht sind. Kann jemand etwas ausarbeiten?

+18

Es gibt einen guten Grund, warum er nicht mehr in Ihrem Team ist ... was Sie haben, ist völlig in Ordnung !!! Es ist nichts falsch daran. – StackFlowed

+0

Wahrscheinlich ist das Timing falsch? Würde dies dazu führen, dass das Programm versucht, "log" zu initialisieren, bevor "LoggerFactory" bereit ist? Sorry, mir ist nicht klar, in welcher Reihenfolge in einem Java-Programm etwas passiert. – ajb

+1

@ajb Natürlich nicht. –

Antwort

13

Der Kommentar wird höchstwahrscheinlich ein Problem der Classloader im Zusammenhang Undichte (here is a good article).

Kurz gesagt, dieses Problem tritt in Umgebungen auf, in denen der Classloader neu geladen werden muss. Wenn Sie eine Klasse dynamisch über einen Klassenlader laden und dann versuchen, den Classloader neu zu laden, können statische Endfelder mit Objekten von Klassen, die durch diesen Classloader erstellt wurden, das Entladen des Classloaders selbst verhindern. Sobald dies passiert, erhalten Sie eine OutOfMemoryError.

Der oben verlinkte Artikel listet die Protokollbibliotheken unter den Top-Täter auf, die dieses Verhalten hervorbringen könnten, zusammen mit Maßnahmen, die Sie ergreifen können, um die Lecks zu umgehen (z. B. das explizite Freigeben von Klassenladeprogrammen).

+0

Wir hatten in der Vergangenheit Diskussionen darüber, Logger für statisch zu erklären und Probleme, die beim Umladen der Klasse auftreten könnten, also vermute ich, dass dies teilweise sein Anliegen war. – sdoca

+1

Hat der 'final'-Modifikator irgendetwas damit zu tun? Startet Classloader-Reloading die statische Variable neu initialisieren, wenn es nicht "final" ist? – Yogu

+0

@Yogu Mein Verständnis ist, dass wenn das Feld nicht final ist, Sie das Problem umgehen können, indem Sie es auf "null" setzen, wenn Sie vor der Deimplementierung bereinigen. Wenn das Feld "final" ist, ist diese Problemumgehung jedoch nicht mehr verfügbar. – dasblinkenlight

12

Die Codezeile ist vollkommen in Ordnung, und es gibt kein echtes Problem, weil die Variable final und static ist.

Vielleicht war die Person, die diesen Kommentar machte, durch das folgende verwirrt. Wenn Sie in Java eine public final static Variable vom Typ int (zum Beispiel; es funktioniert auch mit einigen anderen Typen) erstellen, könnte der Compiler an Stellen, an denen Sie diese Variable verwenden, den tatsächlichen Konstantenwert anstelle von a ersetzen Bezug auf die Variable. Angenommen, Sie haben die folgende:

class A { 
    public final static int VALUE = 3; 
} 

public class B { 
    public static void main(String[] args) { 
     System.out.println(A.VALUE); 
    } 
} 

Wenn Sie diese kompilieren und ausführen, es ist offensichtlich 3.

Nehmen wir nun an, dass Sie Klasse A ändern und VALUE = 4 gedruckt wird. Sie würden erwarten, dass, wenn Sie die Klasse A neu kompilieren und dann die Klasse B ausführen (ohne die Klasse B neu zu kompilieren), würden Sie 4 sehen. Aber was passiert ist, dass Sie immer noch 3 sehen. Dies liegt daran, dass die A.VALUE in Klasse B durch den tatsächlichen konstanten Wert 3 ersetzt wurde, als Sie die Klasse B kompilierten.

Dies ist eine Optimierung, die der Java-Compiler für Konstanten durchführt.

Wie Sie sehen, kann dies zu Problemen führen, wenn Sie solche Konstanten in der öffentlichen API Ihrer Klassen haben. Benutzer Ihres Codes müssen ihren Code neu kompilieren, wenn Sie den Wert solcher Konstanten ändern.

Aber in dem Code, den Sie in Ihrer Frage geschrieben haben, ist dies kein Problem, weil die Variable private ist.

Weitere Details:

Java Language Specification 13.4.9

+0

Danke für das Beispiel. Sehr informativ! – sdoca

Verwandte Themen