2010-02-24 13 views
42

Me preguntaba si el siguiente código tiene algún sentido, ya que el compilador advierte que "los objetos de campo final en blanco pueden no haberse inicializado". ¿Hay una mejor manera de hacer esto?Clase abstracta con campo no inicializado final

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: por el interés en hacer lo correcto. – helios

Respuesta

41

Me gustaría hacer el campo final y obligar a los constructores para pasar el valor de hasta:

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 Me pegó - tenía la misma respuesta, con diferencias triviales (es decir, utilizando un parámetro int y llamando a super() en lugar de this()). – MCory

+0

Gracias. ¿Alguna razón específica por la que la hiciste privada en lugar de protegida? Digamos que quiero acceder directamente en las subclases. ¿Y por qué usa this() en lugar de super()? – Cantillon

+0

@MCory @Lieven Supongo que esta fue una respuesta rápida de un teléfono inteligente, donde no es fácil hacer las cosas bien la primera vez. –

0

En términos generales, podría ser mejor tener un constructor de la clase base que siempre se establece el campo y no tener un constructor predeterminado que no lo configure. Las subclases pueden pasar explícitamente el parámetro en la primera línea de su constructor usando super (valor)

+0

Ooops, lo siento. Eso fue un error de copiar/pegar. He editado mi código. – Cantillon

2

Cree una instancia de los objetos en el constructor de la clase abstracta y simplemente pase la diferencia a ese constructor.

5

El problema con la inicialización de los parámetros finales directamente en el constructor de las subclases es que debe hacerlo todo en una sola línea, ya que super() debe ser la primera instrucción del constructor. Así que, en cambio, prefiero hacer que el constructor no sea público y crear un método de compilación estático como este:

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); 
    } 
} 
Cuestiones relacionadas