Java 中的 null 是什么?

2022-08-31 05:21:49

什么?null

是任何东西的实例吗?null

什么集合属于什么?null

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


答案 1

null 是任何东西的实例吗?

不,没有类型是 .nullinstanceof

15.20.2 类型比较运算符实例

RelationalExpression:
    RelationalExpression instanceof ReferenceType

在运行时,运算符的结果是关系表达式的值不是,并且引用可以强制转换为 ReferenceType 而不引发 .否则,结果为 。instanceoftruenullClassCastExceptionfalse

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


“null”属于哪个集合?

JLS 4.1 类型和值的种类

还有一个特殊的类型,表达式的类型,它没有名称。由于 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

如何使用它。您可以使用它来启用所谓的字段延迟初始化,其中字段的初始值在实际使用之前将具有,并且它被替换为“real”值(计算起来可能很昂贵)。null

还有其他用途。让我们从java.lang.System中举一个真实的例子:

public static Console console()

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

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

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

public String readLine() throws IOException

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

所以在这里,将为每行返回,直到它最终返回一个来表示结束。这允许您按如下方式处理每行: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

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

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

相比之下,java.util.Hashtable通过不允许键和值来使事情变得更简单;如果返回,则明确表示键未映射。nullV get(Object key)null

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

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

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

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

在Java中?没有你的问题。最好保持这种方式。


是一件好事吗?null

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

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

最后,我要引用他自己的发明家C.A.R Hoare(快速排序的名声)的话来结束我的演讲:null

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

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


答案 2

null 是任何东西的实例吗?

不。这就是为什么将返回所有类的原因。(不要被这样一个事实所愚弄,即您可以分配给类型为对象类型的变量。严格来说,赋值涉及隐式类型转换;见下文。null instanceof XfalseXnull

“null”属于哪个集合?

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

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

什么是空值?

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

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

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