Creo que ha expuesto una pregunta más importante detrás de la original: ¿debería trabajar para evitar casos excepcionales en getters y setters?
La respuesta es sí, debe trabajar para evitar excepciones triviales.
Lo que tenemos aquí es efectivamente lazy instantiation que no está motivado en absoluto en este ejemplo:
En la programación informática, la inicialización perezosa es la táctica de retrasar la creación de un objeto, el cálculo de un valor , o algún otro proceso costoso hasta la primera vez que sea necesario.
usted tiene dos problemas en este ejemplo:
Su ejemplo no es seguro para subprocesos. Esa comprobación de nulo puede tener éxito (es decir, encontrar que el objeto es nulo) en dos hilos al mismo tiempo. Su creación de instancias luego crea dos listas diferentes de cadenas. Comportamiento no determinista se producirá.
No hay ninguna buena razón en este ejemplo aplazar la creación de instancias. No es una operación costosa o complicada. Esto es lo que quiero decir con "trabajar para evitar excepciones triviales": vale la pena invertir los ciclos para crear una lista útil (pero vacía) para asegurarse de no lanzar excepciones de puntero nulo de detonación retardada.
Recuerde, cuando infligir una excepción en el código fuera, que está básicamente la esperanza de que los desarrolladores saben cómo hacer algo razonable con él. También estás esperando que no hay un tercer promotor en la ecuación cuya envuelto todo en un comedor de excepción, sólo para ponerse e ignorar excepciones como la suya:
try {
// I don't understand why this throws an exception. Ignore.
t.getStrings();
} catch (Exception e) {
// Ignore and hope things are fine.
}
En el siguiente ejemplo, estoy usando Null Object pattern para indicar al código futuro que su ejemplo no se ha establecido. Sin embargo, el Objeto Nulo se ejecuta como un código no excepcional y, por lo tanto, no tiene los gastos generales y el impacto en el flujo de trabajo de futuros desarrolladores.
public class App {
static class Test {
// Empty list
public static final List<String> NULL_OBJECT = new ArrayList<String>();
private List<String> strings = NULL_OBJECT;
public synchronized List<String> getStrings() {
return strings;
}
public synchronized void setStrings(List<String> strings) {
this.strings = strings;
}
}
public static void main(String[] args) {
Test t = new Test();
List<String> s = t.getStrings();
if (s == Test.NULL_OBJECT) {
// Do whatever is appropriate without worrying about exception
// handling.
// A possible example below:
s = new ArrayList<String>();
t.setStrings(s);
}
// At this point, s is a useful reference and
// t is in a consistent state.
}
}
está bien, pero ¿por qué es malo? – wulfgarpro
@wulfgar: porque debes asegurarte de que tus objetos estén siempre en un estado válido. si se asegura de que nunca permita que un objeto esté en un estado inválido, siempre puede obtener sus propiedades sin preocuparse de que pueda haber algún problema. Además, solo tienes que verificar las cosas una vez (en los incubadores). –
No permite el conocimiento de un estado ilegal de la configuración que no se ha llamado. –