2012-11-23 5 views
17

thể trùng lặp:
Why can’t enum’s constructor access static fields?constructor Tại sao enum không thể truy cập lĩnh vực tĩnh

enum Test { 
    e1,e2;  

    int i=0; 
    static int j=5; 

    Test(){ 
    System.out.println(i+" "+j); 
    } 
} 

Trong đoạn mã trên các nhà xây dựng có thể truy cập các instance variable nhưng không phải là biến tĩnh J

Tôi đã đọc câu trả lời liên quan đến tác giả khác tất cả đều nói e1 và e2 được khởi tạo trước khi khởi tạo của J (trường tĩnh), nhưng theo java spec tất cả các trường tĩnh khởi tạo khi bao giờ lớp được nạp vào bộ nhớ, đó là trước khi chạy của hàm tạo. Vì vậy, trước khi chạy phương thức khởi tạo của Test(), biến tĩnh j phải được khởi tạo. Tôi không thể hiểu được hạn chế, có thể bất kỳ cơ thể nào khiến tôi hiểu được. Tôi đã đọc câu trả lời của các câu hỏi Why can't enum's constructor access static fields? Nhưng tôi không hài lòng với câu trả lời như: -Người xây dựng được gọi trước khi các trường tĩnh có tất cả được khởi tạo.

Giả sử nếu lấy một ví dụ khác với một lớp đơn giản như enum

class Test{ 
    public static final Test t=new Test(); 
    static int a=5; 

    Test(){ 
    System.out.println(a); 
    } 

    public static void main(String[] args) { 
    } 
} 

đây theo có lý lẽ các nhà xây dựng sẽ chạy trước khi khởi tạo của trường tĩnh và nó cũng đang chạy như nó in 0 (Như JVM đã làm bắt đầu). Nhưng không có lỗi biên dịch hoặc không có vấn đề thời gian chạy. Thế thì tại sao điều tương tự cũng không xảy ra với enum.

+1

Câu hỏi hay về thực tế, tôi không thể tìm ra lý do tại sao điều này xảy ra. Có thể có cái gì đó với cách trình biên dịch Java biên dịch tệp lớp. – Gerbrand

+1

Tôi không phải là một chuyên gia java, nhưng không phải là thành viên của một enum ('e1' và' e2' ở trên) về cơ bản các thành viên tĩnh của 'enum'? Và như vậy, khi * chúng * được khởi tạo với các giá trị, hàm tạo phải được gọi ra. Nhưng 'j' vẫn chưa được khởi tạo? –

+0

Mọi enum trong Java là * giống như * một lớp mở rộng 'java.lang.Enum'. Không thể mở rộng 'java.lang.Enum' này bằng một lớp * bình thường * khác. Vì vậy, đối số của bạn rằng "một lớp đơn giản như enum" tạo ra kết quả mong đợi là không hợp lệ. – Prasanth

Trả lời

2

Vấn đề là, các trường hợp của enum được tạo ra trong quá trình inicialization của các trường tĩnh. Và chúng được tạo trước khi khởi tạo các trường tĩnh của bạn. Chúng phải nằm trong các giá trị mảng tĩnh và có thể truy cập tĩnh, do đó, nó có ý nghĩa. Và như đã nêu trong anser để "Tại sao constructor của enum không thể truy cập vào các trường tĩnh?", Thật không may rằng điều này xảy ra trước khi tất cả người dùng định nghĩa trường tĩnh inicialization. Nhưng nếu nó được hoán đổi, bạn không thể truy nhập các cá thể enum trong khởi tạo tĩnh, vì vậy nó sẽ cần cho phép chặn tĩnh cả trước và sau khi tạo các giá trị enum.

Tôi không biết vấn đề là vì việc inicial hóa các giá trị enum là mối quan tâm của lớp Enum (và được xử lý đặc biệt bởi JVM (logic này không nằm trong lớp Enum), hoặc vì bạn không thể đặt trường tĩnh trước giá trị enum.

tẠI SAO nó là cách mà có thể trả lời chỉ có vài người (ví dụ. Josh Bloch và Neal Gafter người được thể hiện theo như tác giả của enum trong javadoc, và có thể một số người khác chưa biết)

6

Nếu bạn tưởng tượng như thế nào enum của bạn sẽ thực sự trông giống như một lớp học, điều đó có ý nghĩa:

public class Test { 
    // Imagine you cannot move these two statements: 
    public static final Test e1 = new Test(); 
    public static final Test e2 = new Test(); 

    int i=0; 
    static int j=5; 

    private Test(){ 
    System.out.println(i+ " " + j); 
    } 

    static int getJ() { 
    return j; 
    } 


    public static void main(String[] args) { 
    System.out.println(Test.getJ()); 
    } 
} 
.210

in này:

0 0 
0 0 
5 

Nếu bạn có thể chia sẻ một ví dụ cụ thể (chứ không phải là một lý thuyết), chúng ta có thể đề nghị làm thế nào để thiết kế lại các mã để đạt được kết quả mong muốn, bất chấp những hạn chế lĩnh vực tĩnh.