Java 中的 null 是什么?

What is null in Java?

提问人:unj2 提问时间:4/25/2010 最后编辑:Joachim Sauerunj2 更新时间:3/9/2018 访问量:388374

问:

什么?null

是任何东西的实例吗?null

属于什么套装?null

它在内存中是如何表示的?

Java null 术语

评论

0赞 Oleksii Kyslytsyn 7/13/2017
叶戈尔256。关于 JLS 的 null。“空字面意思。null 类型有一个值,即 null 引用,由 null 文本 null 表示,该值由 ASCII 字符组成。null 文本始终为 null 类型。关于文章中的要点。“可变和不完整的对象”是一个功能。“缓慢失败”是一种设计能力。“计算机思维与对象思维”只是两种思维方式。“模棱两可的语义”太主观了。“临时错误处理”是另一种处理错误的类型。Null 是 JLS 中指定的文字或其他任何内容,与不好或不好相反。

答:

7赞 Adriaan Stander 4/25/2010 #1

null 关键字是表示 null 引用的文本,该引用不引用任何对象。null 是引用类型变量的默认值。

也可以看看

null : Java 术语表

评论

3赞 user207421 3/30/2016
它不是一个关键词,而是一个字面意思。引用质量差,引用不规范。
10赞 Tom 4/25/2010 #2

不,它不是任何东西的实例,instanceof 将永远是假的。

329赞 polygenelubricants 4/25/2010 #3

null 是任何事物的实例吗?

不,没有类型是 .nullinstanceof

15.20.2 类型比较运算符 instanceof

RelationalExpression:
    RelationalExpression instanceof ReferenceType

在运行时,运算符的结果是,如果 RelationalExpression 的值不是,则可以将引用强制转换为 ReferenceType,而不会引发 .否则,结果是 。instanceoftruenullClassCastExceptionfalse

这意味着对于任何类型和 ,对于任何 ,其中 总是 。ERE oo == nullo instanceof Rfalse


'null' 属于什么集合?

JLS 4.1 类型和值的种类

还有一个特殊的 null 类型,即表达式的类型,它没有名称。由于 null 类型没有名称,因此无法声明 null 类型的变量或强制转换为 null 类型。引用是 null 类型的表达式的唯一可能值。引用始终可以强制转换为任何引用类型。在实践中,程序员可以忽略 null 类型,而只是假装它只是一个特殊的文字,可以是任何引用类型。nullnullnullnull


什么是空?

正如上面引用的 JLS 所说,在实践中,您可以简单地假装它“只是一个特殊的文字,可以是任何引用类型”。

在 Java 中,(在其他语言中并不总是如此)。另请注意,根据合同,它还具有以下特殊属性(来自 java.lang.Object):null == null

public boolean equals(Object obj)

对于任何非参考值,应 .nullxx.equals(null)return false

它也是所有引用类型的默认值(对于具有它们的变量):

JLS 4.12.5 变量的初始值

  • 每个类变量、实例变量或数组组件在创建时都使用默认值进行初始化:
    • 对于所有引用类型,缺省值为 。null

如何使用它各不相同。您可以使用它来启用所谓的字段延迟初始化,其中字段的初始值将一直保留到实际使用之前,然后由“实际”值替换(计算成本可能很高)。null

还有其他用途。让我们以 java.lang.System 为例:

public static Console console()

返回:系统控制台(如果有),否则为 。null

这是一种非常常见的使用模式:用于表示对象不存在。null

这是另一个用法示例,这次来自 java.io.BufferedReader

public String readLine() throws IOException

返回值:包含行内容的 A,不包含任何行终止字符,或者是否已到达流的末尾。Stringnull

所以在这里,将返回每一行,直到它最终返回 a 表示结束。这允许您按如下方式处理每行:readLine()instanceof Stringnull

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

人们可以设计 API,使终止条件不依赖于返回,但可以看出这种设计的好处是使事情变得简洁。请注意,空行没有问题,因为空行 .readLine()null"" != null

让我们再举一个例子,这次来自 java.util.Map<K,V>

V get(Object key)

返回指定键映射到的值,或者如果此映射不包含键的映射。null

如果此映射允许值,则返回值 并不一定表示映射不包含键的映射;映射也有可能将键显式映射到 。该操作可用于区分这两种情况。nullnullnullcontainsKey

在这里,我们开始看到使用如何使事情复杂化。第一条语句说,如果未映射键,则返回。第二条语句说,即使键被映射,也可以返回。nullnullnull

相比之下,java.util.Hashtable 通过不允许键和值来简化事情;它的 , if 返回 ,明确表示键未映射。nullV get(Object key)null

您可以通读其余的 API,并了解使用的位置和方式。请记住,它们并不总是最佳实践示例。null

一般来说,用作特殊值来表示:null

  • 未初始化状态
  • 终止条件
  • 不存在的对象
  • 未知值

它在内存中是如何表示的?

在 Java 中?不用担心。最好保持这种状态。


是一件好事吗?null

这现在是主观的。有人说这会导致许多本来可以避免的程序员错误。有人说,在像 Java 这样的流行语言中,使用它是件好事,因为程序员的错误会很快失败。有些人通过使用 Null 对象模式等来避免。nullNullPointerExceptionnull

这本身就是一个巨大的话题,所以最好把它作为另一个问题的答案来讨论。

最后,我将引用他自己的发明者 C.A.R Hoare(以 quicksort 成名)的话来结束这篇文章:null

称之为我十亿美元的错误。它是 1965 年参考的发明。当时,我正在设计第一个面向对象语言(ALGOL W)的综合类型系统。我的目标是确保所有引用的使用都应该是绝对安全的,并由编译器自动执行检查。但我无法抗拒输入参考的诱惑,仅仅因为它很容易实现。这导致了无数的错误、漏洞和系统崩溃,在过去四十年中可能造成了十亿美元的痛苦和损害。nullnull

本次演示的视频更深入;这是一款值得推荐的手表。

评论

5赞 Stephen C 5/6/2011
1960 年,甚至可能更早,LISP (as) 中就存在空引用。但我不认为 Hoare 真的想在那句话中声称发明了空引用。NIL
10赞 cjs 2/2/2013
Hoare并没有试图声称发明了无效引用;他只是声称他把它们放在一个特别有影响力的地方。有许多语言,包括 Java,显然从 Algol 中汲取了灵感,如果它们对空引用的使用甚至部分受到 Algol 的启发或复制,那么 Hoare 承担这些成本的一些责任是正确的。然而,我确实觉得他的估计相当低。一万亿美元可能更接近真实成本。
0赞 Adam Arold 12/3/2020
这并不能回答问题:(
3赞 Itay Maman 4/25/2010 #4

null是一个特殊值,它不是任何类的实例。以下程序对此进行了说明:

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赞 Sasha Chedygov 4/25/2010
该示例显示的唯一内容是它不是 的实例。nullString
4赞 Thilo 4/25/2010
如果将签名更改为 ,则更有意义。void f(String o)
33赞 Stephen C 4/25/2010 #5

null 是任何事物的实例吗?

不。这就是为什么所有班级都会回来的原因.(不要被可以赋值给类型为对象类型的变量这一事实所迷惑。严格来说,赋值涉及隐式类型转换;见下文。null instanceof XfalseXnull

'null' 属于什么集合?

它是 null 类型的唯一成员,其中 null 类型定义如下:

“还有一种特殊的 null 类型,即表达式 null 的类型,它没有名称。由于 null 类型没有名称,因此无法声明 null 类型的变量或强制转换为 null 类型。null 引用是 null 类型的表达式的唯一可能值。空引用始终可以强制转换为任何引用类型。在实践中,程序员可以忽略 null 类型,而只是假装 null 只是一个特殊的文字,可以是任何引用类型。 JLS 4.1

什么是空?

见上文。在某些上下文中,用于表示“无对象”或“未知”或“不可用”,但这些含义是特定于应用程序的。null

它在内存中是如何表示的?

这是特定于实现的,您将无法在纯 Java 程序中看到 的表示形式。(但在大多数(如果不是全部)Java 实现中表示为零机器地址/指针。nullnull

4赞 fastcodejava 4/25/2010 #6

null是特殊值,它不是任何东西的实例。出于显而易见的原因,它不可能是什么。instanceof

6赞 Thilo 4/25/2010 #7

Null 不是任何类的实例。

但是,您可以将 null 分配给任何(对象或数组)类型的变量:

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

 // but you can still use it as a String
 String x = null;
 "abc".startsWith(null);
9赞 p27 5/6/2011 #8

Java(tm) 中的 Null

在 C 和 C++ 中,“NULL”是在头文件中定义的常量,其值如下:

    0

艺术

    0L

艺术

    ((void*)0)

取决于编译器和内存模型选项。严格来说,NULL 不是 C/C++ 本身的一部分。

在 Java(tm) 中,“null”不是关键字,而是 null 类型的特殊文字。它可以强制转换为任何引用类型,但不能强制转换为任何基元类型,例如 int 或 boolean。null 文本的值不一定为零。并且不可能转换为 null 类型或声明此类型的变量。

16赞 Sanjay Jain 8/31/2011 #9

什么是空?

这没什么。

null 是任何事物的实例吗?

不,因为它什么都不是,它不能是任何事物的实例。

null 属于什么集合?

没有任何设置

它在内存中是如何表示的?

如果一些参考资料指向它,例如:

Object o=new Object();

在堆内存中,为新创建的对象分配了一些空间。o 将指向内存中分配的空间。

现在o=null;

这意味着现在 o 不会指向对象的内存空间。

评论

1赞 Hardik Mishra 9/1/2011
“现在 o=null;这意味着现在 o 不会指向对象的内存空间。我认为这就是 JAVA 中垃圾回收的工作方式
0赞 Bat0u89 11/29/2013 #10

在我看来,在 java 中看到 null 的一种有趣方法是将其视为不表示缺少信息的东西,而只是将其视为可以分配给任何类型的引用的文字值。如果你考虑一下,如果它表示没有信息,那么 a1==a2 为 true 是没有意义的(如果它们都被分配了 null 值),因为它们真的可以指向任何对象(我们根本不知道他们应该指向什么对象)......顺便说一句,null == null 在 java 中返回 true。如果 java 例如像 SQL:1999 一样,那么 null==null 将返回 unknown(SQL:1999 中的布尔值可以采用三个值:true、false 和 unknown,但实际上 unknown 在实际系统中被实现为 null)......http://en.wikipedia.org/wiki/SQL

6赞 Ciro Santilli OurBigBook.com 12/10/2015 #11

字节码表示

Java 具有直接的 JVM 支持:使用三条指令来实现它:null

  • aconst_null:例如,将变量设置为nullObject o = null;
  • ifnull和 : 例如,将对象与ifnonnullnullif (o == null)

第 6 章“Java 虚拟机指令集”然后提到了对其他指令的影响:它为其中许多指令抛出了一个。nullNullPointerException

2.4. “引用类型和值”也以通用术语提及:null

引用值也可以是特殊的 null 引用,即对无对象的引用,此处用 null 表示。null 引用最初没有运行时类型,但可以强制转换为任何类型。引用类型的默认值为 null。

2赞 Anand 1/30/2017 #12

Java 中有两大类类型:原始类型和引用类型。基元类型的声明变量存储值;声明为引用类型的变量存储引用。

String x = null;

在本例中,初始化语句声明变量“x”。“x” 存储字符串引用。此处为 null。首先,null 不是一个有效的对象实例,因此没有为它分配内存。它只是一个值,指示对象引用当前未引用对象。

0赞 Oleksii Kyslytsyn 7/13/2017 #13

简短而准确的答案,正式回答了JLS的所有问题:

3.10.7. Null 文字

null 类型有一个值,即 null 引用,由 null 文字 null,由 ASCII 字符组成。

null 文本始终为 null 类型。

仅分配分配给 null 的类型的引用。您不为引用赋值任何值(对象)。 这种分配特定于 JVM,将占用多少引用以及它将在哪个内存区域中分配。

2赞 user2133061 8/15/2017 #14

Java 中的 null 类似于/类似于 C++ 中的 nullptr。

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;
}

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");
        }
    }
}

现在你从上面的代码中了解 Java 中的 null 是什么了吗?如果没有,那么我建议你学习 C/C++ 中的指针,然后你就会明白。

请注意,在 C 中,与 C++ 不同,nullptr 是未定义的,但使用 NULL,这也可以在 C++ 中使用,但在 C++ 中 nullptr 比 NULL 更可取,因为 C 中的 NULL 始终与指针相关,仅此而已,因此在 C++ 中后缀“ptr”附加到单词的末尾, 而且所有字母现在都是小写的,但这不太重要。

在 Java 中,类非原始类型的每个变量总是引用该类型的对象或继承的,而 null 是 null 类对象引用,但不是 null 指针,因为在 Java 中没有“指针”这样的东西,而是使用对类对象的引用,而 Java 中的 null 与类对象引用相关, 所以你也可以称它为“nullref”或“nullrefobj”,但这很长,所以就叫它“null”吧。

在 C++ 中,您可以将指针和 nullptr 值用于可选成员/变量,即没有值的成员/变量,如果它没有值,则它等于 nullptr,因此例如如何使用 Java 中的 null。