java - La variable es nula en la llamada súper
nullpointerexception null (3)
Estoy usando Java 7 y tengo 3 clases:
TestSuper.java
public abstract class TestSuper {
public TestSuper() {
testMethod();
}
protected abstract void testMethod();
}
TestNull.java
public class TestNull extends TestSuper {
private String test = "Test";
public TestNull() {
super();
System.out.println(test);
}
@Override
protected void testMethod() {
System.out.println(test);
}
}
TestMain.java
public class TestMain {
public static void main(String[] args) {
new TestNull();
}
}
Salida:
null
Test
¿Por qué sucede esto y hay una buena solución para ello?
Cuando llama a new TestNull();
está llamando al constructor de la clase TestNull
, que llama el constructor super()
: contiene una llamada al método implementado en TestNull
, donde imprime el campo String, en este momento los campos de la subclase TestNull
son aún no se ha inicializado, es decir, son nulos.
Después de la llamada al superconstructor, todos los campos se inicializarán y, por lo tanto, la segunda impresión mostrará realmente el nuevo valor de la cadena (inicializada).
El punto clave aquí es que los campos de una subclase se inicializan después de la instanciación de las superclases.
Una solución? Depende de qué comportamiento exacto desee: quizás tenga sentido NO invocar el método abstracto en el superconstructor (es decir, en el constructor de la clase TestSuper
).
De acuerdo con JLS 8.1.1.1 Clase abstracta
Una subclase de una clase abstracta que no es en sí misma abstracta puede ser instanciada, lo que resulta en la ejecución de un constructor para la clase abstracta y, por lo tanto , la ejecución de los Inicializadores de Campo para variables de instancia de esa clase.
Está llamando a un método de instancia anulable (que también llama a un campo de instancia, en su caso private String test = "Test";
) en el constructor. Esto podría causar inconsistencias ya que la instancia no está completamente construida. Esta es una mala práctica, así que evítala:
public TestSuper() {
testMethod();
}
Por favor, lea este hilo: ¿Qué hay de malo con las llamadas a métodos irrevocables en los constructores?