multiple - what is the encapsulation in java




¿Por qué NullPointerException? (2)

Como en JLS §12.5 (Creación de nuevas instancias de clase), el siguiente procedimiento se utiliza cuando se crea una instancia:

  1. Asigne los argumentos del constructor a las variables de parámetros recién creadas para esta invocación del constructor.

  2. Si este constructor comienza con una invocación explícita del constructor (§8.8.7.1) de otro constructor en la misma clase (usando esto), evalúe los argumentos y procese la invocación del constructor de forma recursiva usando estos mismos cinco pasos. Si esa invocación del constructor se completa abruptamente, entonces este procedimiento se completa abruptamente por la misma razón; de lo contrario, continúe con el paso 5.

  3. Este constructor no comienza con una invocación explícita de otro constructor en la misma clase (usando esto). Si este constructor es para una clase que no sea Object, entonces este constructor comenzará con una invocación explícita o implícita de un constructor de superclase (usando super). Evalúe los argumentos y el proceso que la invocación del constructor de superclase recursivamente utiliza estos mismos cinco pasos. Si esa invocación del constructor se completa abruptamente, entonces este procedimiento se completa abruptamente por la misma razón. De lo contrario, continúe con el paso 4.

  4. Ejecute los inicializadores de instancia y los inicializadores de variable de instancia para esta clase, asignando los valores de los inicializadores de variable de instancia a las variables de instancia correspondientes, en el orden en que aparecen textualmente en el código fuente de la clase. Si la ejecución de cualquiera de estos inicializadores da como resultado una excepción, no se procesan más inicializadores y este procedimiento se completa abruptamente con la misma excepción. De lo contrario, continúe con el paso 5.

  5. Ejecuta el resto del cuerpo de este constructor. Si esa ejecución se completa abruptamente, entonces este procedimiento se completa abruptamente por la misma razón. De lo contrario, este procedimiento se completa normalmente.

Eso significa que su llamada a super() y la posterior llamada al método init() anulado se realizan antes de que la variable de instancia se inicie con null que descarta el resultado del método init y sobrescribe cualquier valor que se asigne a mTitle con el valor null .

Esto lleva a la siguiente regla de oro : ¡Nunca se debe llamar a métodos no finales ni privados en un constructor!

Tengo una clase abstracta y una clase derivada. Mira el código provisto: -

public abstract class Parent{
    public Parent(){
        init();
    }

    public abstract void init();    
}



public class Child extends Parent{
    private String mTitle = null;

    public Child(){
        super();
        System.out.println(mTitle.toString());
    }       

    public void init(){
        mTitle = "It' a test";
    }    
}

Cuando ejecutaré el código anterior, lanzará NullPointerException al imprimir el valor de mTitle. Si verifica el código en el constructor del padre, he llamado el método abstracto que llamará el método init de la clase derivada. En el método abstracto, he inicializado el valor del valor de mTitle como = "Es una prueba";

Después de llamar a la clase derivada del constructor principal, debe llamar a System.out.println.

Si se está haciendo de esa manera, entonces por qué está lanzando NullPointerException.

Pero, si acabo de dejar la asignación de mTitle, no se lanzará Excepción como: -

private String mTitle;

Si la inicialización de la variable se produce al llamar a la construcción de la clase y sabemos, por defecto, el objeto global se ha inicializado en nulo. Pero en este caso no lanzará Excepción.


De acuerdo con la Sección 12.5 del JLS , el constructor de la superclase se ejecutará antes del inicializador de mTitle , lo que significa que se volverá a establecer en null después de que se establezca en "It's a test" .







abstract