2012-05-14 22 views
8

Soy consciente de que los constructores de objetos Java inicializan implícitamente los campos no estáticos de su instancia. Sin embargo, no estoy seguro del orden en que esto sucede en una jerarquía de clases. Por ejemplo:Constructor de Java y orden de inicialización de campo

abstract public class AbstractPieceSequence implements PieceSequence 
{ 
    private Tetromino current; 
    private Tetromino preview; 

    public AbstractPieceSequence() 
    { 
     advance(); 
    } 

    @Override 
    public final void advance() 
    { 
     if (preview == null) { 
      current = getNextPiece(); 
      preview = getNextPiece(); 
     } else { 
      current = preview; 
      preview = getNextPiece(); 
     } 
    } 

    abstract protected Tetromino getNextPiece(); 
} 

public class ShufflePieceSequence extends AbstractPieceSequence 
{ 
    private List<Shape> bag = new LinkedList<Shape>(); 

    @Override 
    protected Tetromino getNextPiece() 
    { 
     if (bag.size() == 0) { 
      Collections.addAll(bag, Shape.I, Shape.J, Shape.L, Shape.O, Shape.S, Shape.T, Shape.Z); 
     } 

     return Tetromino.tetrominoes.get(bag.remove(0)); 
    } 
} 

constructor del padre llama a un método en la clase hija, la cual se produce una excepción como el valor de List<Shape> bag es actualmente nula.

Puedo definir un constructor hijo y llamar a super(), pero esa debe ser la primera línea del cuerpo del constructor (lo que significa que todavía no tengo la oportunidad de inicializar el paquete antes de llamar al getNextPiece).

Me falta algo obvio.

Respuesta

15

Correcto. super(), incluso si no lo agrega explícitamente, se coloca implícitamente en cada constructor. Esto significa que el constructor de ShufflePieceSequence se llama primero, pero lo que hace es llamar al AbstractPieceSequence.

En AbstractPieceSequence está llamando a un método definido en ShufflePieceSequence - que no se ha inicializado. De hecho, lo que estás haciendo es en realidad un error muy sutil. Nunca debe llamar a anulables (incluidos los métodos abstract) desde el constructor. Período. Las herramientas AFAIR como y están marcando esto como un posible error.

Ver también

4

Los campos de objeto no se inicializan implícitamente ... debe hacer el inicio. Tal vez necesita un init perezoso en este caso? Generalmente desagradable tener los métodos de llamada del constructor que hacen un trabajo no trivial, por lo general es un olor que algo es más complejo de lo que quiere ser.

3

Profundidad primero, una caminata previa al pedido.

Anders hace una buena observación: Java solo inicializa los campos que son tipos nativos implícitamente. Cualquier campo de Objeto es simplemente una referencia a Objeto, por lo que, de hecho, se inicializó, pero se inicializó en null.

0

El fin de invocar los constructores de la clase de padres y Sub en caso de herencia es que, el constructor de la clase de padres siempre se invoca primero y luego el constructor de la clase Child.

La clase Sub llama al constructor de la clase base de forma predeterminada utilizando el Super(), si no se proporciona explícitamente.

Cuestiones relacionadas