Sự khác biệt về bộ nhớ giữa một biến được gán cho null và một biến không được gán là gì?
Tôi biết rằng có một sự khác biệt trong cách sử dụng, nhưng sự khác biệt trong bộ nhớ là gì?
Sự khác biệt về bộ nhớ giữa một biến được gán cho null và một biến không được gán là gì?
Tôi biết rằng có một sự khác biệt trong cách sử dụng, nhưng sự khác biệt trong bộ nhớ là gì?
Câu trả lời:
Không có sự khác biệt giữa hai "trong bộ nhớ."
Từ Đặc tả ngôn ngữ Java, 4.12,5. Giá trị ban đầu của các biến :
Mỗi biến trong một chương trình phải có một giá trị trước khi giá trị của nó được sử dụng:
- Mỗi biến lớp, biến thể hiện hoặc thành phần mảng được khởi tạo với giá trị mặc định khi nó được tạo (§15.9, §15.10.2):
...
- Đối với tất cả các loại tham chiếu (§4.3), giá trị mặc định là null.
...
- Một biến cục bộ (§14.4, §14,14) phải được cung cấp một giá trị rõ ràng trước khi nó được sử dụng, bằng cách khởi tạo (§14.4) hoặc gán (§15,26), theo cách có thể được xác minh bằng cách sử dụng quy tắc cho phép gán xác định (§ 16 (Bài tập xác định)).
Các biến tham chiếu ở cấp độ hoặc đối tượng sẽ được gán một giá trị null.
Các biến tham chiếu ở mức phương thức (ngăn xếp) sẽ có giá trị không xác định (sử dụng thuật ngữ C ++). Trong thực tế, điều này thường là null, nhưng tiêu chuẩn không chỉ định những gì trong biến tham chiếu, chỉ có điều nó phải được chỉ định trước khi sử dụng. Sử dụng một biến tham chiếu trên ngăn xếp theo bất kỳ cách nào khác ngoài việc gán như lần sử dụng đầu tiên sẽ dẫn đến lỗi biên dịch.
if-then
khối, trình biên dịch sẽ cho bạn biết rằng biến đó có thể chưa được khởi tạo trước trong mã nếu then
khối không được thực thi. Nếu bạn khởi tạo nó để null
biên dịch mã. Tại sao điều đó được đưa ra rằng "một tham chiếu không được gán rõ ràng một giá trị sẽ có giá trị null" ?
null
vì nó sẽ là công việc không cần thiết để làm như vậy.
Sự khác biệt giữa một biến được gán cho null và các biến khác không được gán trong bộ nhớ là gì?
Không có thứ gọi là biến không được gán trong Java. Các thành viên dữ liệu lớp không có phân công rõ ràng được gán giá trị mặc định cho loại, null cho một đối tượng hoặc một cái gì đó gần giống với 0 cho các kiểu nguyên thủy.
Biến cục bộ sống trên stack. (Các địa phương không nguyên thủy như MyType foo
cũng sống trên ngăn xếp, làm tài liệu tham khảo.) Việc phân bổ ngăn xếp rất đơn giản. Nếu một khối chứa khai báo cho các biến cục bộ, không gian cần thiết cho các biến cục bộ đó được dành riêng trên ngăn xếp. Việc các giá trị được gán cho các biến cục bộ đó khi điều chỉnh ngăn xếp để chứa các biến cục bộ đó là không liên quan.
Lý do nó không quan trọng là liệu các biến cục bộ có hoặc không được gán một giá trị tại thời điểm thực hiện nhập vào khối là gấp đôi. Một lý do là kích thước cần thiết không thay đổi. Người nguyên thủy có kích thước cố định và người không nguyên thủy thực sự là tài liệu tham khảo. (Đối tượng được tham chiếu sống trên heap chứ không phải stack.) Lý do thứ hai là việc sử dụng biến cục bộ chưa được gán giá trị là lỗi biên dịch. Điều này tùy thuộc vào thời gian chạy Java liệu có đưa ra một số giá trị (không nhất thiết là mặc định) cho một biến cục bộ được khai báo nhưng không được gán.
if-then
khối, trình biên dịch sẽ cho bạn biết rằng biến đó có thể chưa được khởi tạo trước trong mã nếu then
khối không được thực thi. Nếu bạn khởi tạo nó để null
biên dịch mã. Tại sao điều đó được đưa ra rằng "một tham chiếu không được gán rõ ràng một giá trị sẽ có giá trị null" ? Nhưng nó vẫn chưa đủ rõ ràng đối với tôi. Bạn có thể giải thích nó bằng những từ khác?
null
. Điều này giúp đơn giản hóa rất nhiều sự phát triển của trình gỡ lỗi Java. Nhưng nếu bạn biên dịch với gỡ lỗi bị vô hiệu hóa thì sao? Bây giờ việc khởi tạo là công việc phụ không cần thiết. Những gì trong bộ nhớ đó là không liên quan vì được biết rằng bộ nhớ sẽ chứa một giá trị hợp lệ trong lần sử dụng đầu tiên.
Đầu tiên, thực sự không cần phải lo lắng về không gian được sử dụng bởi các biến cục bộ. Trong một dòng tôi có thể phân bổ một mảng gồm 100.000 số nguyên sẽ chiếm nhiều không gian hơn tất cả các biến cục bộ mà bạn sẽ sử dụng.
Thứ hai, mã của bạn được biên dịch bởi một trình biên dịch có khả năng là thông minh. Nếu biến của bạn không được khởi tạo, nó không được sử dụng (vì trình biên dịch không cho phép sử dụng các biến chưa được khởi tạo). Nhưng nếu bạn khởi tạo nó thành con số không, nó vẫn không được sử dụng! Trình biên dịch sẽ dễ dàng nhận ra rằng nó không được sử dụng và thực tế không sử dụng không gian cho biến. Ngay cả khi nó được sử dụng, trình biên dịch sẽ dễ dàng nhận ra rằng giá trị là 0 và sử dụng nil thay vì biến.
Nhưng thứ ba, đây là tất cả các tối ưu hóa vi mô sẽ không giúp bạn tối ưu hóa chương trình theo bất kỳ cách nào. Bạn đang cố gắng lưu bốn hoặc tám byte. Tập trung vào việc tiết kiệm megabyte nếu bạn muốn tiết kiệm mọi thứ.
Và cuối cùng, trong khi một số người tuyên bố các biến phải luôn được khởi tạo, điều đó không đúng trong Java. Bạn chỉ nên đặt một biến thành một giá trị có ý nghĩa. Giả sử bạn muốn đặt một biến thành tên của một người và bạn quên làm điều này trong một đường dẫn mã. Nếu bạn mù quáng khởi tạo biến thành nil, trình biên dịch không thể cho bạn biết. Nếu không khởi tạo, trình biên dịch có thể và sẽ cho bạn biết về lỗi của bạn.