2012-01-18 35 views
13

Tôi vừa thực hiện một thay đổi mã nhỏ để tắt tiếng cảnh báo FindBugs yêu cầu di chuyển một số mã đến một lớp bên trong vô danh. Để truy cập một số biến, tôi phải khai báo các biến đó là final. Vì vậy, đây là đoạn mã sau khi thay đổi:Khai báo biến cục bộ dưới dạng cuối cùng mà không cần khởi tạo và gán trong if-statement

final File[] libPath; // libPath is final but assignment takes place later 
if (libraryPath != null) { 
    libPath = pathToFiles(libraryPath); 
} else { 
    libPath = new File[0]; 
} 

Điều này chỉ tốt với ngôn ngữ được đặt thành Java 6 trong Eclipse hiện tại (Phiên bản 3.7.1). Tuy nhiên tôi khá chắc chắn điều này được sử dụng để cung cấp cho một lỗi trong một số phiên bản trước đó. Dường như trình biên dịch chấp nhận cấu trúc này khi nó có thể xác định rằng sẽ có.

Câu hỏi của tôi là: điều này có hợp pháp trong Java 6 hoặc là một điều gì đó hiện đang hoạt động do tác dụng phụ của hỗ trợ Java 7 được thêm vào eclipse 3.7.1? Chúng ta đã thấy những tác dụng phụ như vậy với việc sử dụng một số generics hoạt động trong 3.7.1 nhưng không biên dịch trong 3.7.0.

Trả lời

8

Điều này được cho phép và hoạt động tốt kể từ Java 1.1 và sẽ không giúp bạn gặp rắc rối với các trình biên dịch hoặc IDE khác.

Đó là hành vi tiêu chuẩn trong Java và được xác định chính thức đầu tiên trong Java Language Specification 2nd Edition.

+0

Từ nhiều câu trả lời chính xác trỏ đến đặc tả ngôn ngữ, tôi sẽ chấp nhận câu trả lời này vì bạn là người đầu tiên trả lời. – Axel

0

Không sao. Biến không có giá trị và chỉ được gán một lần. Nó sẽ thất bại nếu bạn đã cho nó một giá trị null ban đầu.

0

tôi muốn đề nghị sử dụng mã này để thay thế:

final File[] libPath = ibraryPath == null ? new File[0] : pathToFiles(libraryPath); 

này không phụ thuộc vào bất kỳ phiên bản trình biên dịch, nhưng là 100% được hỗ trợ Java với một ý nghĩa rõ ràng.

+1

Một số người sẽ nói rằng nó cũng phức tạp hơn để đọc;) – ShiDoiSi

+0

Đó là một vấn đề của hương vị, có thể. Nhưng tôi thích nó hơn, bởi vì các biểu thức ở lại các biểu thức và không cần chuyển đổi thành các câu lệnh. Đây cũng là một cấu trúc ngôn ngữ hiện diện trong hầu hết mọi ngôn ngữ kể từ ít nhất C, vì vậy người không thể đọc nó có thể bỏ công việc của mình sớm hơn sau này. – Ingo

13

điều này là ok. nó được gọi là trống thức

trích dẫn từ wiki:

Một biến cuối cùng chỉ có thể được khởi tạo một lần, hoặc thông qua một initializer hoặc một câu lệnh gán. Nó không cần phải được khởi tạo tại điểm tuyên bố: đây được gọi là biến "trống cuối cùng". A biến thể trống cuối cùng của một lớp phải được gán rõ ràng vào cuối mỗi hàm tạo của lớp mà nó được khai báo; tương tự, biến tĩnh cuối cùng trống phải được gán rõ ràng trong trình khởi tạo tĩnh của lớp mà nó được khai báo: nếu không, lỗi biên dịch xảy ra trong cả hai trường hợp. [4] (Lưu ý: Nếu biến là tham chiếu, điều này có nghĩa là biến không thể là bị ràng buộc lại để tham chiếu một đối tượng khác. Nhưng đối tượng mà nó tham chiếu vẫn có thể thay đổi được nếu ban đầu có thể thay đổi.)

trống thức

Các thức trống, được giới thiệu trong Java 1.1, là một biến thức có khai thiếu một initializer. [5] [6] Một trận chung kết trống chỉ có thể được chỉ định một lần và phải được bỏ gán khi một bài tập diễn ra.Trong để thực hiện việc này, trình biên dịch Java chạy phân tích luồng để đảm bảo rằng, cho mỗi lần gán cho biến trống cuối cùng, biến là chắc chắn chưa được gán trước khi gán; nếu không thì một lỗi biên dịch sẽ xảy ra. [7] Nói chung, một trình biên dịch Java sẽ đảm bảo rằng trống cuối cùng không phải là được sử dụng cho đến khi nó được gán giá trị và một khi đã gán giá trị, bây giờ biến cuối cùng không thể được gán lại một giá trị khác. [8]

liên kết: http://en.wikipedia.org/wiki/Final_%28Java%29

+1

Wow, tôi nghĩ rằng tôi biết tất cả cú pháp của Java ít nhất, nhờ giải thích nếp nhăn mới này. – ArtB

1

Java Language Specification chứa toàn bộ một chương dành riêng cho hành vi này (Chapter 16 Definite Assignment).

Hành vi này được xác định kỹ lưỡng, do đó tôi nghĩ bạn hiểu sai điều gì đó khi bạn nói rằng được sử dụng để tạo ra lỗi trong các phiên bản trước.

0

Có, thao tác này sẽ hoạt động và an toàn để sử dụng trong tất cả các phiên bản java tôi đã xem (1.3+).

cuối cùng có nghĩa là bạn không thể thay đổi giá trị của đối tượng khi nó đã được khởi tạo, nếu bạn đặt một giá trị rỗng khi khai báo, nó sẽ bị hỏng.

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