什么是null
?
null
是一个什么样的实例?
null
属于什么样的集合?
它是如何在记忆中表现出来的?
null是什么的实例?
不,没有任何类型的null
是instanceof
。
instanceof
RelationalExpression: RelationalExpression instanceof ReferenceType
在运行时,如果RelationalExpression的值不是
instanceof
,则true
运算符的结果是null
,并且可以在不提高ClassCastException
的情况下将引用强制转换为ReferenceType。否则结果是false
。
这意味着对于任何类型的E
和R
,对于任何E o
,其中o == null
,o instanceof R
总是false
。
“null”属于哪个集合?
还有一个特殊的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)
应该return false
。
对于所有引用类型,它也是默认值(对于具有它们的变量):
- 在创建时,每个类变量,实例变量或数组组件都使用默认值进行初始化: 对于所有引用类型,默认值为
null
。
这是如何使用的。您可以使用它来启用所谓的字段的延迟初始化,其中字段的初始值为null
,直到它实际使用,其中它被“真实”值(可能计算起来很昂贵)所取代。
还有其他用途。让我们从java.lang.System
中得到一个真实的例子:
public static Console console()
返回:系统控制台(如果有),否则为
null
。
这是一种非常常见的使用模式:null
用于表示对象的不存在。
这是另一个用法示例,这次来自java.io.BufferedReader
:
public String readLine() throws IOException
返回:包含行内容的
String
,不包括任何行终止字符;如果已到达流的末尾,则返回null
。
所以在这里,readLine()
会为每一行返回instanceof String
,直到它最终返回一个null
来表示结束。这允许您按如下方式处理每一行:
String line;
while ((line = reader.readLine()) != null) {
process(line);
}
可以设计API,以便终止条件不依赖于返回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
,毫不含糊地表示该键未映射。
您可以阅读其他API并查找null
的使用位置和方式。请记住,它们并不总是最佳实践示例。
一般来说,null
用作特殊值来表示:
它是如何在记忆中表现出来的?
在Java?你没关系。并且最好保持这种方式。
null
a good thing?现在这是主观的边缘主义。有人说null
导致许多程序员错误,这些错误本可以避免。有人说,用一种像Java一样捕获NullPointerException
的语言,使用它是很好的,因为你会在程序员错误上快速失败。有些人通过使用null
等来避免使用Null object pattern。
这本身就是一个很大的话题,因此最好将其作为另一个问题的答案进行讨论。
我将以null
自己的发明者C.A.R Hoare(快速成名)的引言结束这一点:
我称之为十亿美元的错误。这是1965年
null
参考文献的发明。那时,我正在设计第一个用于面向对象语言(ALGOL W)的参考综合类型系统。我的目标是确保所有引用的使用绝对安全,并由编译器自动执行检查。但我无法抗拒引入null
参考的诱惑,仅仅因为它很容易实现。这导致了无数的错误,漏洞和系统崩溃,这可能在过去四十年中造成了数十亿美元的痛苦和损害。
video of this presentation更深入;这是推荐的手表。
instanceof
是一个特殊值,不是任何类的实例。以下程序说明了这一点:
null
Java中的null类似于/类似于C ++中的nullptr。
C ++程序:
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);
}
}
Java中的相同程序:
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中的null吗?如果没有,那么我建议你学习C / C ++中的指针,然后你就会明白了。
请注意,在C语言中,与C ++不同,nullptr是未定义的,但是使用了NULL,也可以在C ++中使用,但在C ++中,nullptr比NULL更优选,因为C中的NULL总是与指针相关,而且它,所以在C ++中,后缀“ptr”被附加到单词的末尾,并且所有字母现在都是小写的,但这不太重要。
在Java中,类型非基本类型的每个变量总是引用该类型的对象或继承而null是null类对象引用,但不是空指针,因为在Java中没有这样的东西“指针”,而是对类的引用使用对象,而Java中的null与类对象引用相关,因此您也可以将其称为“nullref”或“nullrefobj”,但这很长,所以只需将其称为“null”。
在C ++中,您可以使用指针和nullptr值作为可选成员/变量,即没有值的成员/变量,如果它没有值,那么它等于nullptr,因此例如可以使用Java中的null。
在我看来,在java中看到null的有趣方法是将其视为不表示缺少信息的东西,而只是作为可以分配给任何类型的引用的文字值。如果你考虑它,如果它表示缺少信息,那么a1 == a2为真是没有意义的(如果它们都被赋值为null),因为它们可能真的可以指向任何对象(我们只是不知道他们应该指向哪些对象)...顺便说一句,null == null在java中返回true。如果java例如就像SQL:1999然后null == null将返回unknown(SQL中的布尔值:1999可以取三个值:true,false和unknown但实际上未知在实际系统中实现为null)... 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中有两种主要的类型:原始类型和引用类型。声明为基本类型的变量存储值;声明引用类型的变量存储引用。
http://en.wikipedia.org/wiki/SQL
在这种情况下,初始化语句声明变量“x”。 “x”存储字符串引用。它在这里是空的。首先,null不是有效的对象实例,因此没有为其分配内存。它只是一个值,表示对象引用当前不是指对象。
简短而精确的答案,可以从JLS正式回答您的所有问题:
3.10.7。 Null Literal
null类型有一个值,null引用,由null literal null表示,它由ASCII字符组成。
null文字始终为null类型。
仅分配分配给null的类型的引用。您没有为引用分配任何值(对象)。这种分配特定于JVM将花费多少引用以及将分配哪个内存区域。
null是什么的实例?
不。这就是为什么null instanceof X
将为所有类false
返回X
。 (不要被你可以将null
分配给类型为对象类型的变量这一事实所愚弄。严格来说,赋值涉及隐式类型转换;请参阅下文。)
“null”属于哪个集合?
它是null类型的唯一成员,其中null类型定义如下:
“还有一个特殊的null类型,表达式的类型为null,它没有名称。因为null类型没有名称,所以不可能声明null类型的变量或者转换为null类型。 reference是null类型表达式唯一可能的值。null引用总是可以转换为任何引用类型。实际上,程序员可以忽略null类型,只是假装null只是一个特殊的文字,可以是任何引用类型。参考类型。“ JLS 4.1
什么是null?
往上看。在某些情况下,null
用于表示“无对象”或“未知”或“不可用”,但这些含义是特定于应用程序的。
它是如何在记忆中表现出来的?
这是特定于实现的,您将无法在纯Java程序中看到null
的表示。 (但是null
在大多数(如果不是全部)Java实现中都表示为零机器地址/指针。)
什么是null?
没什么。
null是什么的实例?
不,因为它不是什么它不能是任何事情的例子。
null属于什么集合?
没有任何设定
它是如何在记忆中表现出来的?
如果有一些参考指向它:
Object o=new Object();
在堆内存中,一些空间分配给新创建的对象。 o将指向内存中分配的空间。
现在o=null;
这意味着现在o不会指向对象的内存空间。
不,它不是任何实例,instanceof将永远是假的。
Java中的空(tm)
在C和C ++中,“NULL”是头文件中定义的常量,其值如下:
0
要么:
0L
要么:
((void*)0)
取决于编译器和内存模型选项。严格来说,NULL不是C / C ++本身的一部分。
在Java(tm)中,“null”不是关键字,而是null类型的特殊文字。它可以转换为任何引用类型,但不能转换为任何基本类型,如int或boolean。 null文字不一定具有零值。并且无法转换为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 qazxsw poi具有直接的JVM支持:使用三条指令来实现它:
null
:例如在aconst_null
中将变量设置为null
Object o = null;
和ifnull
:例如比较ifnonnull
中的对象和null
然后if (o == null)
提到了Chapter 6 "The Java Virtual Machine Instruction Set "对其他指令的影响:它为其中许多人投掷了一个null
。
NullPointerException
也用通用术语提到2.4. "Reference Types and Values":
引用值也可以是特殊的空引用,对无对象的引用,这里将用null表示。 null引用最初没有运行时类型,但可以转换为任何类型。引用类型的默认值为null。
null
是特殊价值,它不是任何事实。显然,它不能是null
的任何东西。