2012-05-14 26 views
8

Tôi biết rằng các nhà xây dựng đối tượng Java ngầm khởi tạo các trường không tĩnh của cá thể của chúng. Tuy nhiên, tôi không chắc chắn về thứ tự mà điều này xảy ra trong một hệ thống phân cấp lớp. Ví dụ:Java Constructor và Field Initialization Order

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 của cha mẹ gọi một phương thức trong lớp trẻ, mà ném một ngoại lệ như giá trị của List<Shape> bag hiện null.

Tôi có thể định nghĩa hàm khởi tạo con và gọi super(), nhưng đó phải là dòng đầu tiên trong phần thân hàm tạo (có nghĩa là tôi vẫn không có cơ hội khởi tạo túi trước khi gọi getNextPiece).

Tôi thiếu điều gì đó hiển nhiên.

Trả lời

15

Đúng vậy. super(), ngay cả khi bạn không thêm nó một cách rõ ràng, được đặt implictly trong mọi constructor. Điều này có nghĩa là hàm tạo của ShufflePieceSequence được gọi là đầu tiên, nhưng chính điều rất thực hiện là gọi AbstractPieceSequence.

Trong AbstractPieceSequence bạn đang gọi một phương thức được xác định trong ShufflePieceSequence - chưa được khởi tạo. Trong thực tế những gì bạn đang làm thực sự là một lỗi rất tinh vi . Bạn không nên gọi overridable (bao gồm các phương thức abstract) từ hàm tạo. Giai đoạn. Các công cụ AFAIR như đang đánh dấu đây là một lỗi tiềm ẩn.

Xem thêm

4

Trường đối tượng không được khởi tạo ngầm ... bạn cần thực hiện init. Có lẽ bạn cần một init lười biếng trong trường hợp này? Nói chung khó chịu khi có các phương thức gọi phương thức khởi tạo làm công việc không tầm thường, nó thường là một mùi mà một cái gì đó phức tạp hơn nó muốn.

3

Độ sâu đầu tiên, đi bộ đặt trước.

Anders làm cho một điểm tốt: Java chỉ khởi tạo các trường có kiểu gốc một cách ngầm định. Bất kỳ trường Object nào cũng chỉ là một tham chiếu đến Object, và do đó nó được khởi tạo, nhưng nó được khởi tạo thành null.

0

Trình tự cách gọi các nhà thầu của lớp Parent-Sub trong trường hợp thừa kế là, các nhà xây dựng của lớp Chánh luôn luôn được gọi đầu tiên và sau đó là constructor của lớp Child.

Lớp con gọi hàm khởi tạo của lớp cơ sở theo mặc định bằng cách sử dụng Siêu(), nếu không rõ ràng.