2012-09-06 10 views
7

¿Cuándo se inicializa la variable de instancia? ¿Es después de que el bloque del constructor haya terminado o antes?¿Cuándo se inicializan las variables de instancia y se asignan los valores?

Considere este ejemplo:

public abstract class Parent { 

public Parent(){ 
    System.out.println("Parent Constructor"); 
    init(); 
} 

public void init(){ 
    System.out.println("parent Init()"); 
} 
} 

public class Child extends Parent { 

private Integer attribute1; 
private Integer attribute2 = null; 

public Child(){ 
    super(); 
    System.out.println("Child Constructor"); 
} 

public void init(){ 
    System.out.println("Child init()"); 
    super.init(); 
    attribute1 = new Integer(100); 
    attribute2 = new Integer(200); 
} 

public void print(){ 
    System.out.println("attribute 1 : " +attribute1); 
    System.out.println("attribute 2 : " +attribute2); 
} 
} 

public class Tester { 

public static void main(String[] args) { 
    Parent c = new Child(); 
    ((Child)c).print(); 

} 
} 

SALIDA:

Constructor de Padres

Child init()

padre Init()

Constructor Child

atributo 1: 100

atributo 2: null


  1. Cuando el memoria para el atributo 1 & 2 se asignan en el montón?

  2. la curiosidad de saber qué está atributo 2 es NULL?

  3. ¿Hay defectos de diseño?

+0

BTW la terminología de Java, por ejemplo, la variable es "campo". –

Respuesta

10

Cuando la memoria para el atributo 1 & 2 se asignan en el montón?

La memoria para el objeto en su conjunto se asigna cuando se invoca el operador new, antes de entrar en el constructor java.lang.Object. La memoria se asigna para instancias individuales de Integer en init, pero no tiene sentido que la memoria se asigne a propiedades individuales, solo a objetos enteros.

¿Tiene curiosidad por saber por qué el atributo 2 es NULL?

El método init se llama en el super constructor, por lo que se le asigna attribute2new Integer(200), y luego el constructor de la subclase se invoca que se aplica inicializadores de propiedad en el orden en que aparecen en el código fuente. Esta línea

private Integer attribute2 = null; 

sobrescribe el valor asignado por init() a null.

Si se agrega una llamada a

System.out.println("attribute 2 : " +attribute2); 

justo después de su llamada a super(); entonces esto va a ser evidentes.

¿Hay algún defecto de diseño?

Llamar a los métodos de subclase antes de que la clase base haya terminado de inicializarse es peligroso. La subclase puede confiar en los invariantes de su clase base para proteger sus propios invariantes, y si el constructor de la clase base no se ha completado, es posible que sus invariantes no se mantengan.

Esto también puede confundir a los programadores de C++ y similares que esperarían una llamada a init de la clase base para invocar la versión de la clase base ya que C++ reescribe el puntero vtable a medida que se ingresan los constructores.

Ver The Java Language Specification para todos los detalles sangrientos.

+0

Gracias Mike, Diseño: Quise decir que es una buena práctica tener un hijo init() ejecutado antes de su propio constructor. Porque aquí derrota mi propósito de niño init(). ¿Cuál es tu pensamiento sobre esto? – AKh

+0

Además, ¿es una buena práctica tener sus variables de instancia inicializadas como nulas o no? – AKh

+0

@AKh En general, es una mala práctica llamar a métodos dentro del constructor que pueden ser reemplazados por subclases. No quieres que tus subclases puedan romper tu clase. –

1

Después de consumir las respuestas y enlace lleva mi digerir observación:


Este es el ritmo:

  1. Introduzca constructor de la clase del niño. Child() {...}

  2. Invoque explícitamente super() [invocando el constructor de clase principal].

  3. Introduzca Padres() {...} constructor de la clase

  4. invocación súper implícita() [invocando constructor de la clase Object]

  5. Introduzca Object() {} (Sin llamadas súper constructor)

  6. Llamada recursiva para el constructor de super clase final aquí.

  7. vueltas para el constructor de la clase Object

  8. ahora en la clase de padres constructor ... inicializadores de instancia y la instancia inicializadores de variables de clase de padres se ejecuta.

  9. Resto del constructor de la clase de padres se ejecuta y devuelve

  10. Ahora en constructor de la clase del niño. Se ejecutan los inicializadores de instancia y los inicializadores de variables de instancia de la clase Child.

  11. Luego se ejecuta el resto del constructor de la clase Child y finaliza el proceso de inicialización del objeto.


La razón atributo2 era NULL porque

  1. atributo2 se le asigna un valor de 200 @ paso 9.
  2. Pero reemplazado a NULL en el paso 10

¿Hay algún defecto de diseño?

Como Fabian Barney mencione ::::: En general, es una mala práctica llamar a métodos dentro del constructor que pueden ser reemplazados por subclases.

Cuando la memoria para el atributo 1 & 2 se asignan en el montón? Aún pensando. Aprecie cualquier puntero.

Gracias por Mike y Fabian

Cuestiones relacionadas