2013-06-15 37 views
5

Lưu ý: Tôi biết rõ rằng việc khởi tạo nó sẽ khắc phục sự cố; Tôi chỉ giả định trình biên dịch sẽ đi theo con đường thực hiện và thấy rằng foo thực sự sẽ được khởi tạo tại thời điểm mà nó cho thấy nó 'có thể' không được.Hành vi không mong muốn với khởi tạo Java

Giả thiết ban đầu của tôi sẽ là nếu độ dài không bao giờ trên 3, tôi sẽ không bao giờ cần cấp phát bộ nhớ cho nó để sử dụng.

này sẽ không bao giờ được sử dụng trong sản xuất, tôi chỉ đơn giản là tò mò

Xem ví dụ sau: -

List<String> foo; 

int length = 5; 

if (length > 3) 
{ 
    foo = new ArrayList<String>(); 
} 

if (length > 4) 
{ 
    foo.add("bar"); 
} 

Tại sao điều này gây ra sau đây sẽ được hiển thị?

Biến foo địa phương có thể không có được khởi

Chắc chắn sau khi chi nhánh, có bao giờ là một trường hợp trong đó foo không được khởi tạo. Tôi biết rằng nếu tôi phải làm: -

List<String> foo = null; 

sẽ không có vấn đề biên dịch, nhưng tại sao tôi cần phải làm điều này?

+2

@down cử tri, bạn có thể ít nhất cung cấp lý do không? – chrisw

Trả lời

5

Biến cục bộ cần phải được khởi chạy trước khi sử dụng ở bất kỳ nơi nào khác vì nó sẽ không được khởi tạo theo mặc định. Điều gì xảy ra nếu if() không phải là true?

if (length > 3) 
{ 
    foo = new ArrayList<String>(); 
} 

Trình biên dịch không thể biết điều kiện có đúng không.

Một biến cục bộ (§14.4, §14.13) phải được đưa ra một cách rõ ràng giá trị trước khi nó được sử dụng, bởi một trong hai khởi (§14.4) hoặc chuyển nhượng (§15.26), trong một cách mà có thể được xác nhận qua trình biên dịch sử dụng các quy tắc cho xác định nhiệm vụ

như @jlordo chỉ ra làm cho length như final sẽ giải quyết lỗi biên dịch, bởi vì tại thời gian biên dịch tự trình biên dịch biết rằng giá trị của length sẽ luôn luôn được 5 và do đó điều kiện length>3 tôi s luôn luôn true do đó biến địa phương sẽ được khởi tạo.

+1

+1 Đây là điểm - "theo cách có thể được trình biên dịch xác minh". Trình biên dịch có thể về nguyên tắc nói rằng foo luôn được gán trước khi nó được sử dụng ở đây, nhưng không. –

+0

+1 Trích dẫn đó chắc chắn sẽ giải thích tại sao lỗi xảy ra cùng với lời giải thích của bạn – chrisw

5

Trình biên dịch không thể chắc chắn rằng bạn là người đầu tiên nếu khối sẽ được nhập. Nếu không, thì foo sẽ không được khởi tạo. Bạn không thể gọi số add trên biến chưa được khởi tạo. Bạn có thể giúp trình biên dịch bằng cách thực hiện kết quả cuối cùng là length. Trình biên dịch sẽ biết, rằng khối if đầu tiên sẽ được thực hiện.

final int length = 5; 
+0

@ ÓscarLópez: sao chép mã OP, làm cho 'độ dài cuối cùng và lỗi trình biên dịch sẽ biến mất;) – jlordo

+1

@Oscar, cuối cùng không cho phép mã được biên dịch mà không có lỗi; cho dù đây là điều đúng đắn để làm hay không sẽ là một cuộc thảo luận khác – chrisw

+0

@ chrisw69: Chính xác. Tôi chỉ nói rằng điều này sẽ loại bỏ lỗi trình biên dịch. Tôi không nói rằng đó là phong cách tốt. – jlordo

1

Điều này xảy ra vì foo được khởi tạo trong nhánh. Vì vậy, trình biên dịch không chắc chắn nếu foo sẽ được khởi tạo hay không.

2

Vì một cá thể cục bộ không được khởi tạo theo mặc định, không giống như các cá thể lớp hoặc đối tượng.

Từ Java Language Specification:

Một biến cục bộ (§14.4, §14.14) phải được đưa ra một cách rõ ràng giá trị trước khi nó được sử dụng, bởi một trong hai khởi (§14.4) hoặc chuyển nhượng (§15.26), theo một cách có thể được xác minh bởi trình biên dịch bằng cách sử dụng các quy tắc cho phép gán xác định (§16).

Giá trị mặc định:

For type byte, the default value is zero, that is, the value of (byte)0. 
For type short, the default value is zero, that is, the value of (short)0. 
For type int, the default value is zero, that is, 0. 
For type long, the default value is zero, that is, 0L. 
For type float, the default value is positive zero, that is, 0.0f. 
For type double, the default value is positive zero, that is, 0.0d. 
For type char, the default value is the null character, that is, '\u0000'. 
For type boolean, the default value is false. 
For all reference types (§4.3), the default value is null. 
1

Instance và lớp biến được khởi tạo null hoặc 0 giá trị. Nhưng các biến cục bộ thì không. Vì vậy, bạn phải khởi tạo các biến cục bộ trước khi sử dụng nó.

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