Null trong Java là gì?


252

null

nullmột ví dụ của bất cứ điều gì?

Bộ nào nullthuộc về?

Làm thế nào nó được đại diện trong bộ nhớ?


yegor256. Giới thiệu về null từ JLS. "The Null Literal. Loại null có một giá trị, tham chiếu null, được biểu thị bằng null nullal null, được hình thành từ các ký tự ASCII. Một chữ null luôn thuộc loại null." Về điểm trong bài viết. "Các đối tượng có thể thay đổi và không hoàn chỉnh" là một tính năng. 'Thất bại chậm' là một khả năng của thiết kế. 'Suy nghĩ máy tính so với tư duy đối tượng' chỉ là hai cách suy nghĩ. "Ngữ nghĩa mơ hồ" là quá chủ quan. 'Xử lý lỗi đặc biệt' là một loại khác hoạt động với lỗi. Null là một nghĩa đen hoặc bất cứ điều gì khác được chỉ định trong JLS trái ngược với việc không tốt hay xấu.
Oleksii Kyslytsyn

Câu trả lời:


310

Là một ví dụ của bất cứ điều gì?

Không, không có loại nào nulllà một instanceof.

15.20.2 Toán tử so sánh loại instanceof

RelationalExpression:
    RelationalExpression instanceof ReferenceType

Trong thời gian chạy, kết quả của instanceoftoán tử là truenếu giá trị của RelationalExpression không nullvà tham chiếu có thể được chuyển sang ReferenceType mà không tăng a ClassCastException. Nếu không thì kết quả là false.

Điều này có nghĩa là cho bất kỳ loại nào ER, cho bất kỳ E o, ở đâu o == null, o instanceof Rluôn luôn false.


Bộ 'null' thuộc về bộ nào?

JLS 4.1 Các loại và giá trị

Ngoài ra còn có một loại null đặc biệt , loại biểu thức null, không có tên. Vì loại null không có tên, nên không thể khai báo một biến của loại null hoặc chuyển sang loại null . Các nulltham chiếu là giá trị duy nhất có thể có của một biểu hiện của loại. Các nulltài liệu tham khảo luôn có thể được đúc cho bất kỳ loại tài liệu tham khảo. Trong thực tế, lập trình viên có thể bỏ qua loại null và chỉ giả vờ rằng đó nullchỉ là một nghĩa đen đặc biệt có thể thuộc bất kỳ loại tham chiếu nào.


Null là gì?

Như trích dẫn của JLS ở trên, trong thực tế, bạn có thể giả vờ rằng đó "chỉ là một nghĩa đen đặc biệt có thể thuộc bất kỳ loại tham chiếu nào".

Trong Java, null == null(điều này không phải lúc nào cũng đúng trong các ngôn ngữ khác). Cũng lưu ý rằng theo hợp đồng, nó cũng có tài sản đặc biệt này (từ java.lang.Object):

public boolean equals(Object obj)

Đối với bất kỳ nullgiá trị không tham chiếu x, x.equals(null)nên return false.

Nó cũng là giá trị mặc định (cho các biến có chúng) cho tất cả các loại tham chiếu:

Các giá trị ban đầu của biến JLS 4.12.5

  • 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:
    • Đối với tất cả các loại tham chiếu, giá trị mặc định là null.

Làm thế nào điều này được sử dụng khác nhau. Bạn có thể sử dụng nó để kích hoạt cái được gọi là khởi tạo lười biếng của các trường, trong đó một trường sẽ có giá trị ban đầu nullcho đến khi nó thực sự được sử dụng, trong đó nó được thay thế bằng giá trị "thực" (có thể tốn kém để tính toán).

Ngoài ra còn có công dụng khác. Hãy lấy một ví dụ thực tế từ java.lang.System:

public static Console console()

Trả về : Bảng điều khiển hệ thống, nếu có, nếu không null.

Đây là một mẫu sử dụng rất phổ biến: nullđược sử dụng để biểu thị sự không tồn tại của một đối tượng.

Đây là một ví dụ sử dụng khác, lần này là từ java.io.BufferedReader:

public String readLine() throws IOException

Trả về : A Stringchứa nội dung của dòng, không bao gồm bất kỳ ký tự kết thúc dòng nào hoặc nullnếu đã kết thúc luồng.

Vì vậy, ở đây, readLine()sẽ trả về instanceof Stringcho mỗi dòng, cho đến khi cuối cùng nó trả về một nulldấu hiệu kết thúc. Điều này cho phép bạn xử lý từng dòng như sau:

String line;
while ((line = reader.readLine()) != null) {
   process(line);
}

Người ta có thể thiết kế API sao cho điều kiện chấm dứt không phụ thuộc vào việc readLine()trả lại null, nhưng người ta có thể thấy rằng thiết kế này có lợi ích là làm cho mọi thứ trở nên súc tích. Lưu ý rằng không có vấn đề với các dòng trống, bởi vì một dòng trống "" != null.

Hãy lấy một ví dụ khác, lần này là từ java.util.Map<K,V>:

V get(Object key)

Trả về giá trị mà khóa được chỉ định được ánh xạ hoặc nullnếu bản đồ này không chứa ánh xạ cho khóa.

Nếu bản đồ này cho phép nullcác giá trị, thì giá trị trả về nullkhông nhất thiết chỉ ra rằng bản đồ không chứa ánh xạ cho khóa; cũng có thể bản đồ rõ ràng ánh xạ khóa tới null. Các containsKeyhoạt động có thể được sử dụng để phân biệt hai trường hợp này.

Ở đây chúng ta bắt đầu để xem làm thế nào sử dụng nullcó thể làm phức tạp mọi thứ. Câu lệnh đầu tiên nói rằng nếu khóa không được ánh xạ, nullsẽ được trả về. Tuyên bố thứ hai nói rằng ngay cả khi khóa được ánh xạ, cũngnull có thể được trả về.

Ngược lại, java.util.Hashtablegiữ cho mọi thứ đơn giản hơn bằng cách không cho phép nullcác khóa và giá trị; của nó V get(Object key), nếu lợi nhuận null, rõ ràng có nghĩa rằng chìa khóa không được ánh xạ.

Bạn có thể đọc qua phần còn lại của API và tìm vị trí và cách nullsử dụng. Hãy nhớ rằng chúng không phải luôn là ví dụ thực hành tốt nhất .

Nói chung, nullđược sử dụng như một giá trị đặc biệt để biểu thị:

  • Trạng thái chưa được khởi tạo
  • Điều kiện chấm dứt
  • Đối tượng không tồn tại
  • Một giá trị không xác định

Làm thế nào nó được đại diện trong bộ nhớ?

Trong Java? Không phải chuyện của bạn. Và tốt nhất là giữ theo cách đó.


nullmột điều tốt?

Đây là ranh giới chủ quan. Một số người nói rằng nullnguyên nhân gây ra nhiều lỗi lập trình viên có thể tránh được. Một số người nói rằng trong một ngôn ngữ bắt mắt NullPointerExceptionnhư Java, thật tốt khi sử dụng nó bởi vì bạn sẽ thất bại nhanh chóng với các lỗi lập trình viên. Một số người tránh nullbằng cách sử dụng mẫu đối tượng Null , v.v.

Đây là một chủ đề rất lớn, vì vậy nó được thảo luận tốt nhất như là câu trả lời cho một câu hỏi khác.

Tôi sẽ kết thúc điều này bằng một trích dẫn từ nhà phát minh của nullmình, CAR Hoare (của danh tiếng quicksort):

Tôi gọi đó là sai lầm tỷ đô của tôi. Đó là phát minh của nulltài liệu tham khảo vào năm 1965. Vào thời điểm đó, tôi đang thiết kế hệ thống loại toàn diện đầu tiên cho các tài liệu tham khảo bằng ngôn ngữ hướng đối tượng (ALGOL W). Mục tiêu của tôi là đảm bảo rằng tất cả việc sử dụng tài liệu tham khảo phải tuyệt đối an toàn, với việc kiểm tra được thực hiện tự động bởi trình biên dịch. Nhưng tôi không thể cưỡng lại sự cám dỗ để đưa vào một nulltài liệu tham khảo, đơn giản vì nó rất dễ thực hiện. Điều này đã dẫn đến vô số lỗi, lỗ hổng và sự cố hệ thống, có thể gây ra hàng tỷ đô la đau đớn và thiệt hại trong bốn mươi năm qua.

Các video của bài trình bày này đi sâu hơn; đó là một chiếc đồng hồ được đề nghị.


4
Tài liệu tham khảo Null tồn tại trong LISP (as NIL) vào năm 1960, và có lẽ sớm hơn. Nhưng tôi không nghĩ Hoare thực sự đang cố gắng yêu cầu phát minh ra các tài liệu tham khảo null trong trích dẫn đó.
Stephen C

7
Hoare không cố tuyên bố phát minh tài liệu tham khảo null; anh ta chỉ đơn thuần tuyên bố rằng anh ta đã có sẵn chúng ở một nơi có ảnh hưởng đặc biệt. Có nhiều ngôn ngữ, bao gồm cả Java, lấy cảm hứng rõ ràng từ Algol và nếu việc sử dụng các tài liệu tham khảo null của họ thậm chí một phần được lấy cảm hứng từ hoặc sao chép từ Algol, Hoare đã đúng khi nhận một số lỗi cho chi phí của chúng. Tôi cảm thấy, tuy nhiên, ước tính của anh ta là khá thấp. Một nghìn tỷ đô la có thể gần hơn với chi phí thực sự.
cjs

32

Là một ví dụ của bất cứ điều gì?

Không. Đó là lý do tại sao null instanceof Xsẽ trở lại falsecho tất cả các lớp X. (Đừng để bị lừa bởi thực tế là bạn có thể gán nullcho một biến có loại là loại đối tượng. Nói đúng ra, việc chuyển nhượng liên quan đến chuyển đổi loại ẩn; xem bên dưới.)

Bộ 'null' thuộc về bộ nào?

Nó là thành viên duy nhất và duy nhất của loại null, trong đó loại null được định nghĩa như sau:

"Ngoài ra còn có một loại null đặc biệt, loại biểu thức null, không có tên. Bởi vì loại null không có tên, không thể khai báo một biến của loại null hoặc chuyển sang loại null. tham chiếu là giá trị khả dĩ duy nhất của biểu thức loại null. Tham chiếu null luôn có thể được chuyển thành bất kỳ loại tham chiếu nào. Trong thực tế, lập trình viên có thể bỏ qua loại null và chỉ giả vờ rằng null chỉ là một nghĩa đen đặc biệt có thể là bất kỳ Loại tham chiếu." JLS 4.1

Null là gì?

Xem ở trên. Trong một số ngữ cảnh, nullđược sử dụng để biểu thị "không có đối tượng" hoặc "không xác định" hoặc "không khả dụng", nhưng những ý nghĩa này là dành riêng cho ứng dụng.

Làm thế nào nó được đại diện trong bộ nhớ?

Đó là cách triển khai cụ thể và bạn sẽ không thể thấy sự thể hiện nulltrong một chương trình Java thuần túy. (Nhưng nullđược biểu diễn dưới dạng địa chỉ máy / con trỏ bằng 0 trong hầu hết nếu không phải tất cả các triển khai Java.)


14

Null là gì?

Nó không là gì cả

Là một ví dụ của bất cứ điều gì?

Không, vì nó không là gì cả. Nó không thể là ví dụ của bất kỳ thứ gì.

Bộ null nào thuộc về?

Không có bộ nào

Làm thế nào nó được đại diện trong bộ nhớ?

Nếu một số điểm tham chiếu đến nó như:

Object o=new Object();

Trong bộ nhớ heap một số không gian được gán cho đối tượng được tạo mới. Và o sẽ chỉ vào không gian được gán trong bộ nhớ.

Hiện nay o=null;

Điều này có nghĩa là bây giờ o sẽ không trỏ đến không gian bộ nhớ của đối tượng.


1
"Bây giờ o = null; Điều này có nghĩa là bây giờ o sẽ không trỏ đến không gian bộ nhớ của đối tượng." Tôi nghĩ rằng đây là cách Bộ sưu tập rác hoạt động trong JAVA
Hardik Mishra

9

Không, đó không phải là ví dụ của bất cứ điều gì, instanceof sẽ luôn luôn sai.


7

Từ khóa null là một nghĩa đen đại diện cho một tham chiếu null, một từ không tham chiếu đến bất kỳ đối tượng nào . null là giá trị mặc định của các biến kiểu tham chiếu.

Cũng có thể có một cái nhìn vào

null: Thuật ngữ Java


2
Nó không phải là một từ khóa, nó là một nghĩa đen . Chất lượng kém và trích dẫn không quy tắc.
Hầu tước Lorne

6

Null không phải là một thể hiện của bất kỳ lớp nào.

Tuy nhiên, bạn có thể gán null cho các biến thuộc bất kỳ loại (đối tượng hoặc mảng) nào:

 // this is false   
 boolean nope = (null instanceof String);

 // but you can still use it as a String
 String x = null;
 "abc".startsWith(null);

6

Không có trong Java (tm)

Trong C và C ++, "NULL" là hằng số được xác định trong tệp tiêu đề, với giá trị như:

    0

hoặc là:

    0L

hoặc là:

    ((void*)0)

tùy thuộc vào các tùy chọn trình biên dịch và mô hình bộ nhớ. Nói đúng ra, NULL không phải là một phần của chính C / C ++.

Trong Java (tm), "null" không phải là một từ khóa, mà là một nghĩa đen đặc biệt của loại null. Nó có thể được truyền tới bất kỳ loại tham chiếu nào, nhưng không được chuyển sang bất kỳ loại nguyên thủy nào như int hoặc boolean. Chữ null không nhất thiết phải có giá trị bằng không. Và không thể chuyển sang loại null hoặc khai báo một biến của loại này.


5

Đại diện mã byte

Java nullcó hỗ trợ JVM trực tiếp: ba hướng dẫn được sử dụng để thực hiện nó:

  • aconst_null: vd: để đặt một biến thành nullnhư trongObject o = null;
  • ifnullifnonnull: ví dụ để so sánh một đối tượng nullnhư trongif (o == null)

Chương 6 "Bộ hướng dẫn máy ảo Java" sau đó đề cập đến các hiệu ứng của nullcác hướng dẫn khác: nó ném một cái NullPointerExceptioncho nhiều người trong số họ.

2.4. "Các loại tham chiếu và giá trị" cũng đề cập đến nullcác thuật ngữ chung:

Một giá trị tham chiếu cũng có thể là tham chiếu null đặc biệt, tham chiếu đến không có đối tượng, sẽ được ký hiệu ở đây là null. Tham chiếu null ban đầu không có loại thời gian chạy, nhưng có thể được truyền sang bất kỳ loại nào. Giá trị mặc định của loại tham chiếu là null.


4

nulllà giá trị đặc biệt, nó không phải là bất cứ điều gì. Vì lý do rõ ràng nó không thể là instanceofbất cứ điều gì.


3

nulllà một giá trị đặc biệt không phải là một thể hiện của bất kỳ lớp nào. Điều này được minh họa bằng chương trình sau:

public class X {
   void f(Object o)
   { 
      System.out.println(o instanceof String);   // Output is "false"
   }
   public static void main(String[] args) {
      new X().f(null);
   }
}

6
Điều duy nhất mà ví dụ cho thấy đó nullkhông phải là một ví dụ String.
Sasha Chedygov

4
Nếu bạn thay đổi chữ ký thành void f(String o), nó sẽ có ý nghĩa hơn.
Thilo

2

null trong Java giống như / tương tự nullptr trong C ++.

Chương trình trong C ++:

class Point
{
    private:
       int x;
       int y;
    public:
       Point(int ix, int iy)
       {
           x = ix;
           y = iy;
       }
       void print() { std::cout << '(' << x << ',' << y << ')'; }
};
int main()
{
    Point* p = new Point(3,5);
    if (p != nullptr)
    {
       p->print();
       p = nullptr;
    }
    else
    {
        std::cout << "p is null" << std::endl;
    }
    return 0;
}

Cùng một chương trình trong Java:

public class Point {
    private int x;
    private int y;
    public Point(int ix, int iy) {
        x = ix;
        y = iy;
    }
    public void print() { System.out.print("(" + x + "," + y + ")"); }
}
class Program
{
    public static void main(String[] args) {
        Point p = new Point(3,5);
        if (p != null)
        {
            p.print();
            p = null;
        }
        else
        {
            System.out.println("p is null");
        }
    }
}

Bây giờ bạn có hiểu từ các mã ở trên null là gì trong Java không? Nếu không thì tôi khuyên bạn nên học con trỏ trong C / C ++ và sau đó bạn sẽ hiểu.

Lưu ý rằng trong C, không giống như C ++, nullptr không được xác định, nhưng NULL được sử dụng thay thế, nó cũng có thể được sử dụng trong C ++, nhưng trong C ++ nullptr thích hợp hơn chỉ là NULL, vì NULL trong C luôn liên quan đến con trỏ và đó là vì vậy, trong C ++, hậu tố "ptr" đã được thêm vào cuối từ và tất cả các chữ cái đều là chữ thường, nhưng điều này ít quan trọng hơn.

Trong Java, mọi biến của lớp loại không nguyên thủy luôn luôn tham chiếu đến đối tượng của kiểu đó hoặc được kế thừa và null là tham chiếu đối tượng lớp null, nhưng không phải là con trỏ null, vì trong Java không có "con trỏ" nào như vậy, mà tham chiếu đến lớp các đối tượng được sử dụng thay thế và null trong Java có liên quan đến các tham chiếu đối tượng lớp, vì vậy bạn cũng có thể gọi nó là "nullref" hoặc "nullrefobj", nhưng điều này dài, vì vậy chỉ cần gọi nó là "null".

Trong C ++, bạn có thể sử dụng các con trỏ và giá trị nullptr cho các thành viên / biến tùy chọn , ví dụ: thành viên / biến không có giá trị và nếu nó không có giá trị thì nó bằng với nullptr, vì vậy, ví dụ như cách sử dụng null trong Java.


1

Có hai loại chính trong Java: nguyên thủytham chiếu . Các biến được khai báo của một giá trị lưu trữ kiểu nguyên thủy; các biến được khai báo của một kiểu tham chiếu cửa hàng tham chiếu.

String x = null;

Trong trường hợp này, câu lệnh khởi tạo khai báo một biến số x x. Cửa hàng x x kia tham khảo chuỗi. Nó là null ở đây. Trước hết, null không phải là một đối tượng hợp lệ, vì vậy không có bộ nhớ được phân bổ cho nó. Nó chỉ đơn giản là một giá trị chỉ ra rằng tham chiếu đối tượng hiện không tham chiếu đến một đối tượng.


0

Theo tôi, một cách thú vị để xem null trong java là xem nó như một thứ KHÔNG biểu thị sự vắng mặt của thông tin mà chỉ đơn giản là một giá trị theo nghĩa đen có thể được gán cho bất kỳ loại tham chiếu nào. Nếu bạn nghĩ về nó nếu nó biểu thị sự vắng mặt của thông tin thì a1 == a2 là đúng sẽ không có ý nghĩa (trong trường hợp cả hai đều được gán một giá trị null) vì chúng thực sự có thể chỉ vào bất kỳ đối tượng nào (chúng tôi chỉ đơn giản là không biết họ nên trỏ đến đối tượng nào) ... Nhân tiện, null == null trả về true trong java. Nếu java ví dụ như SQL: 1999 thì null == null sẽ trả về ẩn số (một giá trị boolean trong SQL: 1999 có thể lấy ba giá trị: true, false và unknown nhưng trong thực tế chưa biết được triển khai là null trong các hệ thống thực) ... http://en.wikipedia.org/wiki/Query


0

Câu trả lời ngắn và chính xác trả lời tất cả các câu hỏi của bạn chính thức từ JLS:

3.10.7. Chữ Null

Loại null có một giá trị, tham chiếu null, được biểu thị bằng null nullal, được hình thành từ các ký tự ASCII.

Một chữ null luôn thuộc loại null.

Chỉ một tham chiếu của loại được gán cho null được phân bổ. Bạn không gán bất kỳ giá trị (đối tượng) nào cho tham chiếu. Việc phân bổ như vậy là cụ thể cho JVM, sẽ lấy bao nhiêu tham chiếu và trong đó khu vực bộ nhớ sẽ được phân bổ.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.