2009-10-13 57 views

Trả lời

54

Có một số question about this very recently for C# ... - đọc câu trả lời ở đó, vì về cơ bản nó giống nhau. Bạn cũng có thể tìm thấy Eric Lippert's recent blog post thú vị; đó là ít nhất là xung quanh cùng một khu vực, mặc dù nó có một lực đẩy hơi khác nhau.

Về cơ bản, yêu cầu một biến được chỉ định một giá trị trước khi bạn đọc nó là Điều tốt. Nó có nghĩa là bạn sẽ không vô tình đọc một cái gì đó bạn không có ý định. Có, các biến có thể có giá trị mặc định - nhưng không phải là tốt hơn cho trình biên dịch để có thể bắt lỗi của bạn thay vào đó, nếu nó có thể chứng minh rằng bạn đang cố gắng đọc cái gì đó có thể chưa được gán? Nếu bạn muốn đặt giá trị mặc định cho biến cục bộ, bạn luôn có thể gán giá trị đó một cách rõ ràng.

Điều này tốt cho các biến cục bộ - nhưng ví dụ và biến tĩnh, trình biên dịch không có cách nào biết thứ tự mà phương thức sẽ được gọi. Tài sản "setter" có được gọi trước "getter" không? Nó không có cách nào để biết, vì vậy nó không có cách nào để cảnh báo bạn về sự nguy hiểm. Đó là lý do tại sao giá trị mặc định được sử dụng cho ví dụ/biến tĩnh - ít nhất thì bạn sẽ nhận được giá trị đã biết (0, false, null, v.v.) thay vì chỉ "bất kỳ điều gì xảy ra trong bộ nhớ vào thời điểm đó". (Nó cũng loại bỏ vấn đề bảo mật tiềm ẩn khi đọc dữ liệu nhạy cảm chưa được xóa rõ ràng.)

+0

Điều tôi không hiểu là, nếu một đối tượng là rỗng theo mặc định, tại sao bạn phải gán nó cho null? Tôi đoán người dân Java đã quyết định tốt hơn là phải rõ ràng trong trường hợp đó, nhưng tôi không chắc liệu tôi có đồng ý hay không. –

+5

Một đối tượng không phải là rỗng. A * biến * có thể là null, nhưng không phải là một đối tượng. Và một biến cục bộ * không * có giá trị mặc định ... chính xác vì không có nghĩa là bạn buộc phải cung cấp cho nó một giá trị hữu ích trước khi nó được đọc. Nếu bạn muốn làm cho giá trị đó không có giá trị, thì tốt ... nhưng tôi thích trình biên dịch nói với tôi rằng nếu tôi đang cố đọc cái gì đó có thể chưa được khởi tạo ... –

+0

@Jon Ý của bạn là gì? loại bỏ vấn đề bảo mật tiềm ẩn khi đọc dữ liệu nhạy cảm chưa được xóa sạch rõ ràng. " ? Bạn có thể giải thích một chút được không? – Geek

1

Biến cục bộ và nguyên thủy phải được khởi tạo trước khi sử dụng vì bạn biết những gì mong đợi từ các giá trị. Trong lịch sử, khi một biến mới được tạo ra nó sẽ chứa các giá trị ngẫu nhiên từ bộ nhớ [và một không thể dự đoán được giá trị]. Java cũng yêu cầu điều này bởi vì nó ngăn cản sự hiện diện của các biến mồ côi.

0

Trong thực tế, tất cả các biến cần phải được khởi tạo trước khi sử dụng chúng.

Tôi không thể nghĩ ra thời gian bạn muốn sử dụng biến trước khi đặt giá trị của nó (trừ khi bạn so sánh nó với giá trị null).

7

Vâng, trong trường hợp biến cục bộ, rõ ràng nghĩa là 'trước' vì luồng chương trình giữa khai báo (trong phương thức) và tham chiếu là tuần tự. Trong trường hợp các trường được khai báo bên ngoài trình biên dịch phương thức không bao giờ biết mã nào sẽ được sử dụng khi nó không thể tạo ra lỗi như có thể một số phương thức khác sẽ khởi tạo trường trước khi nó được sử dụng.

+0

+1 cho "luồng chương trình giữa khai báo (trong phương pháp) và tham chiếu là tuần tự." – luigi7up

3

Không hoàn toàn đúng sự thật. Các biến cục bộ chỉ cần được khởi tạo nếu tham chiếu. Một biến cục bộ có thể không được khởi tạo nếu không bao giờ được tham chiếu. Ví dụ:

int x; // Valid 
int y; 
println("y=" + y); // Not valid since y's value has never been assigned 
6

Trong Java, lớp và biến mẫu giả định giá trị mặc định (null, 0, false) nếu chúng không được khởi tạo thủ công. Tuy nhiên, các biến cục bộ không có giá trị mặc định. Trừ khi một biến cục bộ được gán một giá trị, trình biên dịch sẽ từ chối biên dịch mã đọc nó. IMHO, điều này dẫn đến kết luận, mà khởi tạo một biến địa phương với một số giá trị mặc định (như null, có thể dẫn đến một NullPointerException sau này) khi nó được khai báo thực sự là một điều xấu. Hãy xem xét ví dụ sau:

Object o; 
if (<some boolean condition>) 
    o = <some value>; 
else 
    o = <some other value>; 
System.out.println(o); 

Một khởi của o với null là hoàn toàn không cần thiết, kể từ khi kiểm tra trình biên dịch Java tại thời gian biên dịch, rằng bất kỳ mã con đường khởi o (với một trong hai null hoặc một số giá trị khác null) trước biến được đọc.Điều đó có nghĩa, trình biên dịch sẽ từ chối biên dịch dòng System.out.println(o); nếu bạn muốn nhận xét bất kỳ khởi tạo nào của biến số o trong đoạn mã ở trên.

Tính năng này dành cho Java và có thể chỉ dành cho Java. Tôi không biết về ngôn ngữ như C#. Tuy nhiên, trong C cũ tốt (và có thể là C++), bạn vẫn nên khởi tạo các biến khi khai báo chúng, AFAIK. Các ngôn ngữ lập trình "cũ" có thể là lý do, rằng khuyến nghị luôn khởi tạo các biến sẽ xuất hiện trong các sách và thảo luận về các ngôn ngữ hiện đại như Java, nơi biên dịch theo dõi liệu biến đã được khởi tạo hay chưa.

+0

Các ngôn ngữ "cũ" khuyến cáo không khai báo biến cho đến khi bạn có một giá trị để đặt vào. :-) –

+0

Hãy xem xét ví dụ ở trên. Làm thế nào bạn có thể có một giá trị để đưa vào một biến, nếu giá trị phụ thuộc vào kết quả của một câu lệnh if phức tạp. IMHO, quy tắc bạn đề xuất có vấn đề lớn. – Sven

+0

Nếu giá trị cần một số tính toán phức tạp, bạn có thể đặt các giá trị đó vào một hàm riêng biệt và sử dụng lệnh gọi hàm làm bộ khởi tạo. –

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