2010-02-24 9 views
42

Mi chiedevo se il codice seguente abbia un senso, poiché il compilatore avverte che "gli oggetti campo finale vuoto potrebbero non essere stati inizializzati". C'è un modo migliore per farlo?Classe astratta con campo non inizializzato finale

public abstract Test { 
    protected final ArrayList<Object> objects; 
} 

public TestSubA extends Test { 

    public TestSubA() { 
    objects = new ArrayList<Objects>(20); 
    // Other stuff 
    } 
} 

public TestSubB extends Test { 

    public TestSubB() { 
    objects = new ArrayList<Objects>(100); 
    // Other stuff 
    } 
} 
+5

+1: per l'interesse a fare la cosa giusta. – helios

risposta

41

vorrei fare il campo finale e costringere i costruttori a passare il valore up:

public abstract class Test { 
    private final ArrayList<Object> objects; 

    protected ArrayList<Object> getObjects() { 
    return objects; 
    } 

    protected Test(ArrayList<Object> objects) { 
    this.objects = objects; 
    } 
} 

public class TestSubA extends Test { 

    public TestSubA() { 
    super(new ArrayList<Object>(20)); 
    // Other stuff 
    } 
} 

public class TestSubB extends Test { 

    public TestSubB() { 
    super(new ArrayList<Object>(100)); 
    // Other stuff 
    } 
} 
+0

+1 Mi ha battuto - ha avuto la stessa risposta, con differenze banali (cioè usando un parametro int e chiamando super() invece di questo()). – MCory

+0

Grazie. Qualche motivo specifico per cui l'hai reso privato anziché protetto? Diciamo che voglio accedervi direttamente nelle sottoclassi. E perché usi questo() invece di super()? – Cantillon

+0

@MCory @Lieven Immagino sia stata una risposta rapida da uno smartphone, dove non è facile ottenere tutto correttamente la prima volta. –

0

In generale, potrebbe essere meglio avere un costruttore nella classe base che imposta sempre il campo e non ha un costruttore predefinito che non lo imposta. Le sottoclassi possono quindi passare esplicitamente il parametro nella prima riga del costruttore mediante super (valore)

+0

Ooops, mi dispiace. Quello era un errore di copia/incolla. Ho modificato il mio codice. – Cantillon

2

Creare un'istanza degli oggetti nel costruttore della classe astratta e passare semplicemente la differenza al costruttore.

5

Il problema con l'inizializzazione dei parametri finali direttamente nel costruttore delle sottoclassi è che è necessario eseguire tutto in una riga poiché super() deve essere la prima istruzione del costruttore. Quindi, preferisco rendere il costruttore non pubblico e creare un metodo di compilazione statico come questo:

public abstract class Test { 
    protected final ArrayList<Object> objects; 

    protected Test(ArrayList<Object> objects) { 
    this.objects = objects; 
    } 
} 

public class TestSubA extends Test { 
    public static TestSubA build() { 
    ArrayList<Object> objects = new ArrayList<Object>(20); 
    objects.put(...); 
    // Other stuff 
    return new TestSubA(objects); 
    } 

    private TestSubA(ArrayList<Object> objects) { 
    super(objects); 
    } 
} 
Problemi correlati