null
是什么?
null
是任何实例吗?
null
属于哪个集合?
它在内存中如何表示?
null
是什么?
null
是任何实例吗?
null
属于哪个集合?
它在内存中如何表示?
空值是某个实例吗?
不是的,没有任何类型可以让 null
成为其 instanceof
实例。
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
.
E
和 R
,对于任何 E o
,其中 o == null
,o instanceof R
总是 false
。
还有一种特殊的null类型,即表达式
null
的类型,它没有名称。因为null类型没有名称,所以无法声明null类型的变量或将其强制转换为null类型。null
引用是null类型表达式的唯一可能值。null
引用始终可以转换为任何引用类型。在实践中,程序员可以忽略null类型,只需假装null
仅是一个可以是任何引用类型的特殊字面量。
什么是null?
正如上面的JLS引用所说,在实践中,你可以简单地假装它是“只是一个可以是任何引用类型的特殊字面量”。
在Java中,null == null
(在其他语言中并不总是这样)。还要注意,按照合同,它还具有这个特殊属性(来自java.lang.Object
):
public boolean equals(Object obj)
对于任何非
null
引用值x
,x.equals(null)
应该返回false
。
对于所有引用类型,它也是所有引用类型变量的默认值(如果有的话):
这个用法有所不同。您可以使用它来启用所谓的惰性初始化字段,其中字段将具有其初始值
- 每个类变量、实例变量或数组组件在创建时都会初始化为默认值:
- 对于所有引用类型,缺省值为
null
。
null
,直到实际使用它时,它被“真实”值(可能计算代价高昂)替换。java.lang.System
中拿一个真实的例子:
这是一种非常常见的用法模式:
public static Console console()
返回:系统控制台(如果有),否则为
null
。
null
用于表示对象不存在。java.io.BufferedReader
:
因此,在这里,
public String readLine() throws IOException
返回:包含行内容但不包括任何行终止字符的
String
,或者null
,如果已到达流的末尾。
readLine()
会为每行返回String
的实例,直到最终返回null
以表示结束。这使您可以按以下方式处理每行:String line;
while ((line = reader.readLine()) != null) {
process(line);
}
readLine()
返回null
,但可以看出这种设计的好处在于使事情更简洁。请注意,空行没有问题,因为空行"" != null
。java.util.Map<K,V>
:
V get(Object key)
返回映射到指定键的值,如果此映射不包含键的映射,则返回null
。
如果此映射允许null
值,则null
的返回值并不一定表示该映射不包含键的映射;也有可能映射将键明确地映射到null
。可以使用containsKey
操作来区分这两种情况。
null
会使事情变得复杂。第一个语句表示,如果未映射键,则返回null
。第二个语句表示,即使键已映射,也可以返回null
。java.util.Hashtable
更简单,因为它不允许使用null
键和值;如果V get(Object key)
返回null
,则意味着该键没有映射关系。null
的使用位置和方式。请记住,它们并不总是最佳实践的例子。null
用作特殊值,表示:
它在内存中是如何表示的?
在Java中?你不需要关心。最好保持这种状态。
null
是否好?现在这已经是一个有争议的问题了。有些人认为null
会导致许多本可以避免的程序员错误。有些人则认为,在像Java这样捕获NullPointerException
的语言中,使用它是好的,因为你会快速地检测到程序员错误。一些人通过使用Null对象模式等方式来避免使用null
。
这是一个很大的话题,最好作为回答另一个问题来讨论。
我将以null
的发明者C.A.R Hoare(快速排序的创始人)的话来结束:
我称之为我的十亿美元错误。 这是在1965年发明
null
引用的时候。当时,我正在设计第一个面向对象语言(ALGOL W)中引用的全面类型系统。我的目标是确保所有引用的使用都是绝对安全的,并由编译器自动执行检查。但我无法抵制放置一个null
引用的诱惑,仅仅因为它非常容易实现。这导致了无数的错误、漏洞和系统崩溃,可能在过去四十年里造成了十亿美元的痛苦和损失。
这个演示的视频更深入,建议观看。
NIL
表示)早在1960年就存在,可能更早。但我认为Hoare并不是真正试图声称他发明了空引用。 - Stephen Cnull是任何实例吗?
不是。这就是为什么对于所有类X,“null instanceof X”都将返回“false”的原因。(不要被您可以将null分配给对象类型的变量所欺骗。严格来说,该赋值涉及隐式类型转换;请参见下文。)
‘null’属于哪个集合?
它是null类型的唯一成员,其中null类型定义如下:
“还有一个特殊的null类型,即表达式null的类型,它没有名称。由于null类型没有名称,所以无法声明null类型的变量或将其强制转换为null类型。 null引用是null类型表达式的唯一可能值。 null引用始终可以转换为任何引用类型。在实践中,程序员可以忽略null类型,并假装null只是一个可以是任何引用类型的特殊文字。” JLS 4.1
null是什么?
请参见上文。在某些情况下,null用于表示“无对象”、“未知”或“不可用”,但这些含义是应用程序特定的。
它在内存中是如何表示的?
这取决于具体实现方式,您无法在纯Java程序中查看null的表示形式。(但在大多数Java实现中,null表示为零机器地址/指针。)
null是什么?
null表示空值。
null是某个实例吗?
不是,因为null表示空值,它不能是任何实例。
null属于哪个集合?
null不属于任何集合。
null在内存中如何表示?
如果有一些引用指向它,比如:
Object o=new Object();
在堆内存中,新创建的对象会被分配一些空间。o将指向内存中分配给该对象的空间。
现在o=null;
这意味着现在o不再指向该对象的内存空间。
不,这不是任何东西的实例,instanceof 操作符总是返回 false。
Java中的Null
C和C++中,"NULL"是在头文件中定义的一个常量,它的值如下:
0
或者:
0L
或者:
((void*)0)
根据编译器和内存模型选项的不同,NULL并不严格属于C/C++本身。在Java中,“null”不是关键字,而是特殊的null类型字面量。它可以转换为任何引用类型,但不能转换为任何原始类型,如int或boolean。空字面值不一定具有零值。无法将其转换为null类型或声明此类型的变量。
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);
字节码表示
Java中的null
在JVM上有直接的支持:它使用了三个指令来实现:
aconst_null
:例如将变量设置为null
,如:Object o = null;
ifnull
和ifnonnull
:例如将对象与null
进行比较,如:if (o == null)
第6章“Java虚拟机指令集”然后提到了null
对其他指令的影响:它会对其中许多指令抛出NullPointerException
。
2.4.“引用类型和值”也以通用术语提及null
:
引用值还可以是特殊的null引用,即不指向任何对象的引用,在这里用null表示。null引用最初没有运行时类型,但可以转换为任何类型。引用类型的默认值为null。
null
是一个特殊的值,它不是任何东西的实例。显然,它不能是任何东西的 instanceof
。
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);
}
}
null
不是String
的一个实例。 - Sasha Chedygov