2012-03-12 33 views
10

Tôi gặp sự cố khi hiểu thứ tự khởi tạo xảy ra. đây là thứ tự tôi cho rằng:Thứ tự khởi tạo khối và định nghĩa biến và vv được thực thi theo thứ tự nào? (trong java)

*Once per 
    1. Static variable declaration 
    2. Static block 
*Once per object 
    3. variable declaration 
    4. initialization block 
    5. constructor 

nhưng theo mã này tôi rõ ràng là sai:

class SomethingWrongWithMe 
    { 
     { 
      b=0;   //no. no error here. 
      int a = b; //Error: Cannot reference a field before it is defined. 
     } 
     int b = 0; 
    } 

Và lỗi sẽ biến mất nếu tôi làm điều này:

class SomethingWrongWithMe 
    { 
     int b = 0; 
     { 
      b=0; 
      int a = b; //The error is gone. 
     } 
    } 

tôi có thể không tìm ra lý do tại sao không có lỗi trên

b=0; 
+0

Trình biên dịch nào bạn đang sử dụng? Oracles javac? Hoặc một số IDE (ít nhất Eclipse mang trình biên dịch riêng của nó) –

+0

Eclipse và Oracles javac hoạt động giống nhau trong kịch bản này. – aioobe

+1

sử dụng nhật thực .. – Untitled

Trả lời

4

Java Language Specification (phần 8.3.2.3) nói rằng bạn có thể sử dụng một biến ở bên trái Mặt bên của một biểu thức, nghĩa là gán cho nó, trước khi nó được khai báo, nhưng bạn không thể sử dụng nó ở phía bên tay phải.

Tất cả các biến được khởi tạo thành giá trị mặc định của chúng, sau đó trình khởi tạo rõ ràng và khối ẩn danh được chạy theo thứ tự chúng được tìm thấy trong tệp nguồn. Cuối cùng, hàm tạo được gọi.

Thống kê chỉ được chạy một lần khi sử dụng lần đầu tiên một lớp học.

Lỗi biên dịch có vẻ như là một quy tắc của Java thay vì điều gì đó nhất thiết phải có ý nghĩa trong mọi trường hợp.

+0

câu hỏi tiếp theo: ok. Bây giờ tôi hiểu tình hình ở đây. không thể hiểu tại sao lại có một tính năng như vậy. Tôi không thể tưởng tượng một sử dụng cho nó.tại sao một người nào đó muốn gán cho một biến trong khối khởi tạo trước khi khai báo của nó? tại sao không chỉ tuyên bố nó trước? – Untitled

+1

Tôi đồng ý và tại sao chúng tôi có thể chỉ định giá trị cho nó, nhưng không đọc từ nó? JLS cho biết tất cả các biến được tạo và được khởi tạo thành các giá trị mặc định trước khi bất kỳ mã rõ ràng nào được chạy, do đó biến tồn tại và có giá trị, chúng tôi không thể đọc từ đó. Điều đó có vẻ lạ với tôi. –

+0

Nó được thực hiện để tránh tham chiếu vòng tròn. Ví dụ. int a = b + 1; int b = a + 2; – ekaerovets

1

Trước hết, giả định của bạn ít nhiều chính xác, ngoại trừ thực tế là các khai báo (với khởi tạo, chẳng hạn như int b = 0) và các khối khởi tạo thể hiện được thực hiện theo thứ tự chúng được viết.

int b = 0; // executed first 

{ 
    b = 1; // executed second 
} 

int a = b; // executed third 

Cũng lưu ý rằng tờ khai ví dụ int b không thực hiện. Tuyên bố chỉ tuyên bố sự tồn tại của biến.

Đối với lỗi bạn nhận được (hoặc, thay vì lỗi bạn không nhận được) Tôi đồng ý rằng nó có vẻ lạ. Tôi giả định rằng trình biên dịch đề cập đến việc tham chiếu một biến trong một biểu thức và gán một giá trị cho biến đó theo các cách khác nhau. Khi viết vào một biến trong một khởi tạo thể hiện, nó chỉ kiểm tra xem biến đó có ở đó không, trong khi khi đọc nó, nó yêu cầu nó được khai báo phía trên khối khởi tạo thể hiện. Tôi sẽ xem nếu tôi có thể tìm thấy một tham chiếu cho điều đó trong JLS.

3

Định nghĩa biến không được thực hiện "trước khi" chặn. Cả hai đều thực hiện tại cùng một thời điểm, theo thứ tự mà chúng được định nghĩa

class SomethingWrongWithMe { 
    { 
     b = debug("block 1"); 
    } 
    int b = debug("define"); 
    { 
     b = debug("block 2"); 
    } 
    private int debug(String str) { 
     System.out.println(str); 
     return 0; 
    } 
} 

Output

block 1 
define 
block 2 
+1

Phải, nhưng câu hỏi tại sao anh ta có thể ghi vào một biến được khai báo bên dưới dòng nhưng không đọc từ cùng một biến không được trả lời. – aioobe

Các vấn đề liên quan