2015-07-19 25 views
5
  • Erstes BeispielDifferenz zwischen einem statischen Endfeld und ein letzten Instanz Feld bei Deklaration initialisiert, wenn

    public class MyClass { 
        final int x = 2; 
    } 
    

    durch ein Objekt zugegriffen x ist

    1. final was es bedeutet, kann nach der Initialisierung niemals eingestellt werden.
    2. Bei der Deklaration initialisiert, was bedeutet, dass ihm später (auch im Konstruktor) kein anderer Wert zugewiesen werden kann.
    3. behoben (unabhängig von der Instanz), da sein Wert im Konstruktor (oder anderswo wirklich) nicht geändert werden kann.
  • Zweites Beispiel

    public class MyOtherClass { 
        static final int x = 3; 
    } 
    

    x ist

    1. letzte das heißt, es kann nie nach der Initialisierung eingestellt werden.
    2. Bei der Deklaration initialisiert, was bedeutet, dass später kein anderer Wert zugewiesen werden kann.
    3. ein statische Feld und der Wert wird immer gleich bleiben, unabhängig von der Instanz.
    4. konstant weil es sowohl statische und letzte.

Meine Fragen sind

Was sind die Unterschiede zwischen den beiden sind? (ohne Erstellungszeit)

Fehle ich etwas?

+0

Dies ist meine erste Frage also, fühlen Sie sich frei, den Stil zu kommentieren und wenn ich improv e es. – naaz

+0

Wenn Sie eine endgültige Variable zur Deklarationszeit initialisieren, sollte sie wahrscheinlich statisch sein ... – assylias

+1

Ein möglicher Unterschied ist, dass ein 'static final'-Primitiv zur Laufzeit nicht verwendet wird. Der Compiler hätte alle Vorkommen während des Kompilierens durch den Wert ersetzt, wodurch er optimiert wurde. – Codebender

Antwort

6

Die Unterschiede zwischen x in MyClass und MyOtherClass sind:

  • die erste nur über eine MyClass Instanz und es können mehrere Kopien der konstant zugegriffen werden.

  • der zweite kann ohne MyOtherClass Instanz zugegriffen werden und nur eine Kopie kann existieren.

In Ihrem Beispiel gibt es keinen praktischen Unterschied zwischen einer oder mehreren Instanzen der Konstante. Beachten Sie jedoch Folgendes:

public class YetAnotherClass { 
    final int x; 

    public YetAnotherClass(int x) { 
     this.x = x; 
    } 
} 

... zeigt, wie eine Instanzkonstante unterschiedliche Werte in verschiedenen Instanzen haben kann.


1 - Das ist eine Übertreibung. Zunächst deklariert static final int x = 3; eine Kompilierzeitkonstante, und eine Kompilierzeitkonstante kann in einem Schalterkassenausdruck verwendet werden, bei dem eine Nicht-Kompilierzeitkonstante nicht verwendet werden kann. Zweitens wird die nicht-statische Version der Konstante Platz in jeder Instanz von MyClass einnehmen. Schließlich gibt es Unterschiede im Verhalten, wenn Sie so dämlich sind, zu versuchen, die Konstanten durch Reflexion zu ändern. (Tun Sie es einfach nicht ...)

+0

Konnte der Analyse/JIT-Optimierungs-Cache-Wert von x entkommen, wenn nur 'final int x' verwendet wird? – TheLostMind

+0

Möglicherweise. Der Code müsste jedoch immer noch funktionieren, wenn auf die Konstante mithilfe von Reflektion zugegriffen wird. Daher müsste das Feld wahrscheinlich trotzdem zugewiesen werden. –

+0

macht Sinn. Dies würde dann auch für 'static final int' gelten. – TheLostMind

1

Obwohl final, die JVM macht keine Optimierungen oder Annahmen, so dass jede Instanz der Klasse eine Instanz von x haben wird. Wenn Sie das Mitglied static deklarieren, wird jede Instanz der Klasse die gleiche Instanz von x teilen, da es statisch zugewiesen ist. Darüber hinaus können andere Klassen, wie geschrieben (x hat Paketsichtbarkeit), möglicherweise statisch auf x zugreifen, d. H. Ohne dass eine Instanz der Klasse verfügbar ist.

1

Wenn Sie dann mehr Instanzen beiden Typen von Klassen erstellen

In First Szenario alle Objekte von MyClass würden eigenes final x Feld haben.

Wo wie im zweiten Szenario alle Objekte von MyOtherClass Punkte auf ein final x Klassenfeld als, weil es statisch in der Natur ist.

+0

Ich denke im zweiten Fall, dass die Objekte von 'MyOtherClass' nicht auf das' statische final x' zeigen. Es gehört zur Klasse und nicht zum Objekt. – Codebender

+0

ja, dats richtig, ich habe versucht, das gleiche darzustellen. –

1

Unterschied: Statisch gehört zur Klasse So Sie können es ohne jede Instanz der Klasse und damit nur eine Kopie davon zugreifen.

Für den Zugriff auf die zweite benötigen Sie eine Instanz einer Klasse, um darauf zuzugreifen, so dass Sie so viele Kopien von nicht statischen endgültigen Objekten haben können, wie sie zu Object gehören.

Sie können mit Byte-Code bestätigen: für statische

Code: 
     stack=1, locals=1, args_size=1 
     0: aload_0 
     1: invokespecial #1     // Method java/lang/Object."<init>":()V 
     4: return 

Für Nicht-Static Finale

Code: 
     stack=2, locals=1, args_size=1 
     0: aload_0 
     1: invokespecial #1     // Method java/lang/Object."<init>":()V 
     4: aload_0 
     5: iconst_2 
     6: putfield  #2     // Field x:I 
     9: return 
     LineNumberTable: 

Wie Sie sehen, es ist hat putfield, die den Wert des Feldes setzt identifiziert in objektref (ein Verweis auf ein Objekt)

+3

Es verblüfft mich, dass Leute denken, dass es eine gute Idee ist, Anfängern die Java-Sprache zu erklären, indem sie ihnen Bytecode-Sequenzen zeigen. –

+2

@StephenC - Verteidigung dieser Antwort .. Diese Antwort könnte auch für andere (Zwischenstufe?) Nützlich sein :) .. Nicht nur die OP .. – TheLostMind

+1

@StephenC Es ist nur für jedermann :) –