Inizializza in campo, costruttore o argomento

0

Se so a cosa verrà inizializzato un campo, dovrei inizializzarlo nel campo, costruttore o riceverlo come parametro? Sto chiedendo le migliori pratiche. Tutte e tre le opzioni forniscono in modo efficace lo stesso risultato. Non sto considerando quello che succede dietro le quinte, perché penso che sarebbe insignificante.

Questa è una domanda generale per curiosità. Al momento non ho un problema specifico, anche se in passato. Userò un ArrayList nel seguente esempio, perché è un caso in cui si sa a cosa verrà inizializzato, e se si finisce volendo inizializzarlo su un altro ArrayList esistente, non c'è nulla di male pre-inizializzandolo. O c'è?

Ad esempio, dove dovrei inizializzare un ArrayList?

Inizializzato nel campo:

import java.util.ArrayList;

public class Initializer {
    private ArrayList<String> arrayList = new ArrayList<String>();

    public void addString(String string) {
        arrayList.add(string);
    }
}

Inizializzato in Constructor:

import java.util.ArrayList;

public class Initializer {
    private ArrayList<String> arrayList;

    public Initializer() {
        arrayList = new ArrayList<String>();
    }

    public void addString(String string) {
        arrayList.add(string);
    }
}

Inizializzato come parametro:

import java.util.ArrayList;

public class Initializer {
    private ArrayList<String> arrayList;

    public Initializer(ArrayList arrayList) {
        this.arrayList = arrayList;
    }

    public void addString(String string) {
        arrayList.add(string);
    }
}
    
posta Evorlor 19.12.2014 - 22:24
fonte

2 risposte

6

L'inizializzazione come parametro interrompe l'incapsulamento in quanto il chiamante può quindi fare con la lista passata ciò che vuole (cancella in momenti dispari).

ArrayList<String> list = new ArrayList<String>();
Initializer init = new Initializer(list);
//do various thing
list.clear();
//now the list in init is also empty while init may still expect it to be filled

Per le altre 2 opzioni dipende da cosa vuoi inizializzare con:

Ad esempio una classe che ha bisogno di una coda thread-safe potrebbe usare una delle varie implementazioni (elenco collegato, buffer circolare, ecc.) Il costruttore può decidere quale utilizzare in base ai parametri o quale costruttore è stato chiamato e anche passare i parametri al costruttore dell'oggetto.

public Initializer(boolean useLinked) {
    if(useLinked){
        this.arrayList = new LinkedList<String>();
    else 
        this.arrayList = new ArrayList<String>();
}

Se l'implementazione sarà sempre la stessa, inizializzala nel campo o nel blocco di inizializzazione e contrassegnala come definitiva.

public class Initializer {
    private final ArrayList<String> arrayList = new ArrayList<String>();
}

Ciò impedisce ad altri metodi di sovrascriverlo accidentalmente.

    
risposta data 19.12.2014 - 22:31
fonte
0

If I know what a field will be initialized to

Se lo sai, allora è molto probabile che la tua classe non sarà molto riusabile o commetterai l'errore di presumere che saprai come la tua classe sarà usata ora e in futuro - mentre in realtà manchi qualche possibile casi d'uso. Posso spiegarlo più dettagliatamente se fornisci maggiori informazioni su ciò che la classe deve fare semanticamente.

Di solito è meglio andare con Inizializzazione per parametro (assumendo che l'argomento cambierà e non sempre sarà una lista vuota, come detto sopra). Questo design è anche chiamato depedency injection . Ha alcuni vantaggi. Per esempio. uno di questi è molto più testabile.

Dovresti utilizzare le interfacce invece di accettare solo tipi concreti. Quindi dovresti fare per:

//(...)
private List<String> someList ;

    public Initializer(List someList ) {
        this.someList = someList ;
    }

E qualcuno può quindi creare un nuovo inizializzatore di new Initializer(new ArrayList()) OPPURE può fare qualcosa come new Initializer(new CopyOnWriteArrayList()) poiché in alcuni casi questo sarà molto più performante. L'utente della classe può decidere meglio, che tipo di lista vuole usare. E tu, come creatore di classe, non ti importa se è un ArrayList o CopyOnWriteArrayList giusto? Devi solo avere un List -thing in cui puoi aggiungere elementi nello stesso modo.

    
risposta data 19.12.2014 - 23:06
fonte

Leggi altre domande sui tag