2015-07-19 30 views
5
  • Primo esempiodifferenza tra un campo finale statico e un campo di ultima istanza inizializzata dichiarazione quando accede attraverso un oggetto

    public class MyClass { 
        final int x = 2; 
    } 
    

    x è

    1. finale che significa che non può mai essere impostato dopo l'inizializzazione.
    2. Inizializzato alla dichiarazione che significa che non può avere un valore diverso assegnato successivamente (anche nel costruttore).
    3. corretto (indipendentemente dall'istanza) perché il suo valore non può essere modificato nel costruttore (o in qualsiasi altro luogo realmente).
  • Secondo esempio

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

    x è

    1. finale che significa che può non essere impostato dopo l'inizializzazione.
    2. Inizializzato alla dichiarazione che significa che non può avere un valore diverso assegnato in seguito.
    3. a campo statico e il valore rimarrà sempre lo stesso indipendentemente dall'istanza.
    4. costante perché è sia statico e finale.

Le mie domande sono

Quali sono le differenze tra i due? (escluso il tempo di creazione)

Mi manca qualcosa?

+0

Questa è la mia prima domanda quindi, sentitevi liberi di commentare lo stile e se posso improvvisare e lui. – naaz

+0

Se si inizializza una variabile finale al momento della dichiarazione, probabilmente dovrebbe essere statica ... – assylias

+1

Una differenza potenziale è una primitiva 'static final' non utilizzata durante il runtime. Il compilatore avrebbe sostituito tutte le occorrenze di esso con il valore durante la compilazione rendendolo più ottimizzato. – Codebender

risposta

6

Le differenze tra x in MyClass e MyOtherClass sono:

  • il primo si può accedere solo tramite un'istanza MyClass e possono essere presenti più copie della costante.

  • il secondo è accessibile senza l'istanza MyOtherClass e può esistere solo una copia.

Nel tuo esempio, non v'è alcuna differenza pratica tra l'avere una o più istanze del costante. Tuttavia considera questo:

public class YetAnotherClass { 
    final int x; 

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

... che mostra come una costante di istanza può avere valori diversi in diverse istanze.


1 - E 'un'esagerazione. Innanzitutto, static final int x = 3; sta dichiarando una costante in fase di compilazione e una costante in fase di compilazione può essere utilizzata in un'espressione caso di scambio, in cui una costante non a tempo di compilazione non può. In secondo luogo, la versione non statica della costante occuperà spazio in ogni istanza di MyClass. Infine, ci saranno differenze di comportamento se sei abbastanza sciocco da provare a cambiare le costanti usando la riflessione. (Basta non farlo ...)

+0

Potrebbe eseguire l'escape dell'analisi/valore di cache dell'ottimizzazione JIT di x quando viene utilizzato solo 'final int x'? – TheLostMind

+0

Possibilmente. Tuttavia, il codice avrebbe ancora bisogno di funzionare se si accede alla costante usando il reflection, quindi il campo dovrebbe probabilmente essere allocato comunque. –

+0

ha senso. Questo si applicherebbe anche a 'static final int'. – TheLostMind

1

Anche se final, la JVM non esegue ottimizzazioni o ipotesi, quindi ogni istanza della classe avrà un'istanza di x. Se dichiari il membro static, ciascuna istanza della classe condividerà la stessa istanza di x perché è allocata staticamente. Inoltre, come scritto (x ha visibilità del pacchetto), altre classi possono potenzialmente accedere a x staticamente, cioè senza avere un'istanza della classe disponibile.

1

Se si creano più istanze di entrambi i tipi di classi, allora,

In Primo scenario tutti gli oggetti di MyClass avrebbe proprio final x campo.

Dove, come nel secondo scenario, tutti gli oggetti di MyOtherClass hanno punti per un campo di classe final x poiché sono di natura statica.

+0

Penso che nel secondo caso, l'oggetto di 'MyOtherClass' non punti affatto a' static final x'. Appartiene alla classe e non all'oggetto. – Codebender

+0

sì, stammi bene, ho provato a ritrarre lo stesso. –

1

Differenza: Statico appartiene alla classe Quindi è possibile accedervi senza alcuna istanza della classe e quindi solo una sua copia.

Mentre per accedere al secondo è necessario l'istanza di una classe per accedervi in ​​modo da poter disporre di un numero di oggetti finale non statico pari a quello di Object.

è possibile verificare con il codice Byte: Per Statico

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

per i non-statico 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: 

Come si può vedere che offre putfield che imposta il valore del campo identificato in objectref (riferimento ad un oggetto)

+3

Mi sconcerta il fatto che la gente pensi che sia una buona idea spiegare il linguaggio Java ai principianti mostrandoli sequenze bytecode. –

+2

@StephenC - difendere questa risposta .. Questa risposta potrebbe essere utile per gli altri (livello intermedio?) Pure :) .. Non solo l'OP .. – TheLostMind

+1

@StephenC È solo per tutti :) –