Java 中的 null 是什么? [英] What is null in Java?
问题描述
什么是null
?
null
是任何东西的实例吗?
null
属于哪个集合?
它在内存中是如何表示的?
null 是任何东西的实例吗?
不,不存在 null
是 instanceof
的类型.
15.20.2 类型比较运算符 instanceof
<块引用>关系表达式:RelationalExpression 实例的 ReferenceType
在运行时,如果RelationalExpression 的值不是null,
instanceof
运算符的结果是true
code> 并且引用可以转换为 ReferenceType 而不会引发 ClassCastException
.否则结果为 false
.
这意味着对于任何类型E
和R
,对于任何E o
,其中o == null
>, o instanceof R
总是 false
.
'null'属于哪个集合?
JLS 4.1 类型的种类和价值观
<块引用>还有一个特殊的null类型,表达式null
的类型,它没有名字.由于 null 类型没有名称,因此无法声明 null 类型的变量或强制转换为 null 类型.null
引用是 null 类型表达式的唯一可能值.null
引用始终可以转换为任何引用类型.在实践中,程序员可以忽略 null 类型并假装 null
只是一个可以是任何引用类型的特殊文字.
<小时><块引用>
什么是空?
正如上面的 JLS 引用所说,在实践中,您可以简单地假设它只是一个可以是任何引用类型的特殊文字".
在 Java 中,null == null
(在其他语言中并非总是如此).另请注意,根据合同,它还具有此特殊属性(来自 java.lang.Object
):
public boolean equals(Object obj)
对于任何非<code>null引用值x
,x.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() 抛出 IOException
返回:包含行内容的String
,不包括任何行终止符,或者null
,如果行的结尾已到达流.
所以在这里,readLine()
将为每一行返回 instanceof String
,直到它最终返回一个 null
来表示结束.这允许您按如下方式处理每一行:
字符串行;while ((line = reader.readLine()) != null) {流程(线);}
可以设计 API 使终止条件不依赖于 readLine()
返回 null
,但是可以看到这种设计的好处是东西简洁.注意空行没有问题,因为空行"" != null
.
再举一个例子,这次来自 java.util.Map
:
V get(Object key)
返回指定键映射到的值,如果此映射不包含键的映射,则返回 null
.
如果此映射允许 null
值,则返回值 null
并不一定表示该映射不包含该键的映射;也有可能映射显式地将键映射到 null
.containsKey
操作可用于区分这两种情况.
在这里,我们开始看到使用 null
如何使事情复杂化.第一条语句表示,如果键未映射,则返回 null
.第二个语句表示即使键被映射,null
也可以也返回.
相比之下,java.util.Hashtable
通过不允许 null
键和值使事情变得更简单;它的V get(Object key)
,如果返回null
,明确表示key没有映射.
您可以通读其余的 API 并了解 null
的使用位置和使用方式.请记住,它们并不总是最佳实践示例.
一般来说,null
作为一个特殊的值来表示:
- 未初始化状态
- 终止条件
- 不存在的对象
- 未知值
它在内存中是如何表示的?
在 Java 中?不关你事.最好保持这种状态.
<小时>null
是好事吗?
这现在是主观的边缘.有人说 null
会导致许多本可以避免的程序员错误.有人说,在像 Java 这样捕获 NullPointerException
的语言中,最好使用它,因为您将在程序员错误时快速失败.有些人通过使用空对象模式等来避免null
.>
这本身就是一个巨大的话题,因此最好将其作为另一个问题的答案进行讨论.
我将引用 null
的发明者本人的话作为结尾,CAR Hoare(快速排序成名):
我称之为我的十亿美元错误.这是 1965 年 null
引用的发明.当时,我正在设计第一个综合类型系统面向对象语言 (ALGOL W) 中的引用.我的目标是确保所有引用的使用都绝对安全,并由编译器自动执行检查.但是我无法抗拒放入 null
引用的诱惑,仅仅因为它很容易实现.这导致了无数错误、漏洞和系统崩溃,在过去的四十年里,这些问题可能造成了 10 亿美元的痛苦和损失.
本次演示视频 更深入;值得推荐的手表.
What is null
?
Is null
an instance of anything?
What set does null
belong to?
How is it represented in the memory?
Is null an instance of anything?
No, there is no type which null
is an instanceof
.
15.20.2 Type Comparison Operator instanceof
RelationalExpression: RelationalExpression instanceof ReferenceType
At run time, the result of the
instanceof
operator istrue
if the value of the RelationalExpression is notnull
and the reference could be cast to the ReferenceType without raising aClassCastException
. Otherwise the result isfalse
.
This means that for any type E
and R
, for any E o
, where o == null
, o instanceof R
is always false
.
What set does 'null' belong to?
JLS 4.1 The Kinds of Types and Values
There is also a special null type, the type of the expression
null
, which has no name. Because the null type has no name, it is impossible to declare a variable of the null type or to cast to the null type. Thenull
reference is the only possible value of an expression of null type. Thenull
reference can always be cast to any reference type. In practice, the programmer can ignore the null type and just pretend thatnull
is merely a special literal that can be of any reference type.
What is null?
As the JLS quote above says, in practice you can simply pretend that it's "merely a special literal that can be of any reference type".
In Java, null == null
(this isn't always the case in other languages). Note also that by contract, it also has this special property (from java.lang.Object
):
public boolean equals(Object obj)
For any non-
null
reference valuex
,x.equals(null)
shouldreturn false
.
It is also the default value (for variables that have them) for all reference types:
JLS 4.12.5 Initial Values of Variables
- Each class variable, instance variable, or array component is initialized with a default value when it is created:
- For all reference types, the default value is
null
.
How this is used varies. You can use it to enable what is called lazy initialization of fields, where a field would have its initial value of null
until it's actually used, where it's replaced by the "real" value (which may be expensive to compute).
There are also other uses. Let's take a real example from java.lang.System
:
public static Console console()
Returns: The system console, if any, otherwise
null
.
This is a very common use pattern: null
is used to denote non-existence of an object.
Here's another usage example, this time from java.io.BufferedReader
:
public String readLine() throws IOException
Returns: A
String
containing the contents of the line, not including any line-termination characters, ornull
if the end of the stream has been reached.
So here, readLine()
would return instanceof String
for each line, until it finally returns a null
to signify the end. This allows you to process each line as follows:
String line;
while ((line = reader.readLine()) != null) {
process(line);
}
One can design the API so that the termination condition doesn't depend on readLine()
returning null
, but one can see that this design has the benefit of making things concise. Note that there is no problem with empty lines, because an empty line "" != null
.
Let's take another example, this time from java.util.Map<K,V>
:
V get(Object key)
Returns the value to which the specified key is mapped, or
null
if this map contains no mapping for the key.If this map permits
null
values, then a return value ofnull
does not necessarily indicate that the map contains no mapping for the key; it's also possible that the map explicitly maps the key tonull
. ThecontainsKey
operation may be used to distinguish these two cases.
Here we start to see how using null
can complicate things. The first statement says that if the key isn't mapped, null
is returned. The second statement says that even if the key is mapped, null
can also be returned.
In contrast, java.util.Hashtable
keeps things simpler by not permitting null
keys and values; its V get(Object key)
, if returns null
, unambiguously means that the key isn't mapped.
You can read through the rest of the APIs and find where and how null
is used. Do keep in mind that they aren't always the best practice examples.
Generally speaking, null
are used as a special value to signify:
- Uninitialized state
- Termination condition
- Non-existing object
- An unknown value
How is it represented in the memory?
In Java? None of your concern. And it's best kept that way.
Is null
a good thing?
This is now borderline subjective. Some people say that null
causes many programmer errors that could've been avoided. Some say that in a language that catches NullPointerException
like Java, it's good to use it because you will fail-fast on programmer errors. Some people avoid null
by using Null object pattern, etc.
This is a huge topic on its own, so it's best discussed as answer to another question.
I will end this with a quote from the inventor of null
himself, C.A.R Hoare (of quicksort fame):
I call it my billion-dollar mistake. It was the invention of the
null
reference in 1965. At that time, I was designing the first comprehensive type system for references in an object oriented language (ALGOL W). My goal was to ensure that all use of references should be absolutely safe, with checking performed automatically by the compiler. But I couldn't resist the temptation to put in anull
reference, simply because it was so easy to implement. This has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused a billion dollars of pain and damage in the last forty years.
The video of this presentation goes deeper; it's a recommended watch.
这篇关于Java 中的 null 是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!