2009-07-25 21 views
5

Qual è la differenza tra questi due metodi di inizializzazione dell'osservatore ArrayList. O qualsiasi altro tipo per quella materia. È uno più veloce dell'altro? O mi sto perdendo qualche altro vantaggio qui.Java: Qual è la differenza tra questi metodi di costruzione

class Publisher implements Observerable 
{ 
    private ArrayList observers = new ArrayList(); 
} 

class Publisher implements Observerable 
{ 
    private ArrayList observers; 

    public Publisher() 
    { 
     observers = new ArrayList(); 
    } 
} 

risposta

13

Sono equivalenti. Infatti, se si compila il due vedrete che essi generano esattamente lo stesso codice di byte:

Publisher(); 
    Code: 
    0: aload_0 
    1: invokespecial #1; //Method java/lang/Object."<init>":()V 
    4: aload_0 
    5: new  #2; //class java/util/ArrayList 
    8: dup 
    9: invokespecial #3; //Method java/util/ArrayList."<init>":()V 
    12: putfield  #4; //Field observers:Ljava/util/ArrayList; 
    15: return  
} 

Dato che sono lo stesso codice, c'è chiaramente non può esserci alcuna differenza di velocità :)

Nota che in C# non sono del tutto equivalenti - in C# l'inizializzatore per observers dovrebbe essere prima della chiamata del costruttore di base; in Java sono davvero gli stessi.

Che si utilizza è una questione di gusti. Se hai diversi costruttori diversi che inizializzano tutte le variabili nello stesso modo in cui avrebbe senso usare il primo modulo. D'altra parte, è generalmente una buona idea se ci sono diversi costruttori per provare a fare in modo che molti di loro chiamino un costruttore "principale" che fa il lavoro vero e proprio.

+1

Jon Skeet colpiscono di nuovo –

+1

Non si ottiene anche lo stesso bytecode con un'istanza di inizializzazione? Direi che la risposta è sì. –

+1

@mmyers: Sì, esattamente lo stesso di nuovo. –

4

sono uguali, ma: la differenza è che nell'ultimo esempio, si guadagna il vantaggio di essere in grado di fare la logica di inizializzazione più avanzata: la gestione degli errori, ecc

1

Non c'è davvero alcuna differenza. Un vantaggio del primo modo è che se si dispone di più costruttori, non è necessario ricordare di inizializzare lo observers in tutti.

Nel secondo esempio, è possibile essere più flessibili, se si desidera regolare il valore in base agli argomenti del costruttore.

2

L'unica vera differenza è nell'ordine delle operazioni. I campi inizializzati nella loro dichiarazione vengono valutati prima che venga chiamato il costruttore della classe. I campi inizializzati in una sottoclasse in questo modo verranno valutati dopo il completamento del costruttore del super, ma prima che venga chiamato il costruttore della sottoclasse.

consideri il seguente esempio:

ho una classe di test:

public class Tester { 
    Tester (String msg) { 
     System.out.println(this + ":" + msg); 

    } 
} 

ho una classe di super:

public class Test { 

    protected Tester t1 = new Tester("super init block"); 

    Test (String constructorMsg) { 
    new Tester(constructorMsg); 
    } 
} 

e ho una sottoclasse:

Public class TestSub extends Test { 

    private Tester t2 = new Tester("sub init block"); 

    TestSub(String constructorMsg) { 
     super(constructorMsg); 
     new TTester("sub constructor"); 
    } 

} 

Nel mio main metodo, creo un'istanza di TestSub:

public static void main(String[] args) { 
    new TestSub("super constructor"); 

} 

i risultati sono i seguenti: modifiche

[email protected]:super init block 
[email protected]:super constructor 
[email protected]:sub init block 
[email protected]:sub constructor 
+0

Tutto ciò che dice, per l'esempio mostrato nella domanda, non c'è * nessuna differenza * - perché il costruttore nella seconda versione consiste solo della stessa chiamata come nell'inizializzatore del campo nella prima versione. È importante sottolineare che l'inizializzatore di campo viene chiamato * dopo * il supercostruttore, non prima. –

Problemi correlati