2010-03-30 19 views

Trả lời

4

Như được thảo luận bằng các câu trả lời khác, không, điều đó không thể xảy ra. Tuy nhiên, với trường tĩnh cuối cùng được gán, nó có thể.

class MyClass { 
    private static MyClass myClass = new MyClass(); 
    private static final Object obj = new Object(); 
    public MyClass() { 
    System.out.println(obj); // will print null once 
    } 
} 
+1

Cảm ơn! Và điều này dẫn đến http://stackoverflow.com/questions/2547713/why-static-fields-are-not-initialized-in-time –

+0

Đây là từ một thời gian dài trước đây, nhưng tôi chỉ muốn nói rằng mặc dù điều này có thể không xảy ra, nó làm với tôi. Điều duy nhất tôi có thể nghĩ đến là bởi vì đó là GWT mà tôi đang xử lý, vì vậy nó là Java được biên dịch chéo với JScript. – Jamie

2

Trình khởi tạo Object obj = new Object(); sẽ chạy trước mã bên trong hàm tạo, vì vậy obj không thể là null.

Lưu ý rằng điều này sẽ không biên dịch nếu bạn không khởi tạo obj ở bất kỳ đâu.

2

trình cho tôi:

$ cat MyClass.java 
class MyClass { 
    private final Object obj = new Object(); 
    public MyClass() { 
     System.out.println(obj); // may print null? 
    } 
    public static void main(String[] args) { new MyClass(); } 
} 
$javac MyClass.java; java MyClass 
[email protected] 

Tất cả initializers lĩnh vực được sao chép bởi trình biên dịch thành sự khởi đầu của tất cả các nhà xây dựng.

Tuy nhiên, theo mô hình bộ nhớ Java 5, nếu bạn để cho this tham khảo 'thoát' trước khi kết thúc các nhà xây dựng, chủ đề khác có thể thấy giá trị chưa được khởi tạo của final lĩnh vực (như vậy có thể thấy null trong trường hợp này).

+0

nó không phải là âm tính của tôi, nhưng bạn đang nói về cái gì? –

+0

Đoạn cuối mô tả tình huống duy nhất tôi biết nơi có thể thấy giá trị của trường cuối cùng có giá trị chưa được khởi tạo của nó. Xem "Các trường cuối cùng hoạt động như thế nào trong JMM mới?" của http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html –

+0

+1 - xem thêm https://www.securecoding.cert.org/confluence/pages/ viewpage.action? pageId = 32833640 –

3

Điều này là không thể với tư cách là tất cả initializers run before the constructor is invoked.

Trình khởi tạo biến như bạn có private final Object obj = new Object(); chạy trước khi hàm tạo được gọi. Điều này cũng đúng với các khối khởi tạo tĩnh hoặc ngược lại.

Một điều cần lưu ý khi sử dụng công cụ khởi tạo là trình khởi tạo không thể chuyển tiếp tham chiếu Khi bạn viết trình khởi tạo, bạn không thể tham chiếu đến bất kỳ biến mẫu nào được khai báo văn bản sau khi biến được khởi tạo.

2

Với ví dụ đơn giản như của bạn, không có gì xấu có thể xảy ra. Tuy nhiên, nó có thể cho trường final để hiển thị dưới dạng chưa được khởi tạo nếu bạn sử dụng các thực tiễn có vấn đề như gọi phương thức có thể ghi đè trong hàm tạo của bạn.

Ví dụ: chương trình sau in "Màu yêu thích của tôi là rỗng", mặc dù nó tham chiếu biến cuối cùng favouriteColour, được đặt thành "blue" trong hàm tạo.

abstract class SuperClass { 
    final String favouriteColour; 

    SuperClass() { 
     announceFavouriteColour(); 
     favouriteColour = "blue"; 
    } 

    abstract void announceFavouriteColour(); 
} 

public class FinalTest extends SuperClass { 
    void announceFavouriteColour() { 
     System.out.println("My favourite colour is " + favouriteColour); 
    } 

    public static void main(String[] args) { 
     new FinalTest(); 
    } 
} 
Các vấn đề liên quan