Java中的null是什么?

问题描述 投票:226回答:14

什么是null

null是一个什么样的实例?

null属于什么样的集合?

它是如何在记忆中表现出来的?

java null terminology
14个回答
294
投票

null是什么的实例?

不,没有任何类型的nullinstanceof

15.20.2 Type Comparison Operator instanceof

RelationalExpression:
    RelationalExpression instanceof ReferenceType

在运行时,如果RelationalExpression的值不是instanceof,则true运算符的结果是null,并且可以在不提高ClassCastException的情况下将引用强制转换为ReferenceType。否则结果是false

这意味着对于任何类型的ER,对于任何E o,其中o == nullo instanceof R总是false


“null”属于哪个集合?

JLS 4.1 The Kinds of Types and Values

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


什么是null?

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

在Java中,null == null(在其他语言中并非总是如此)。还要注意,通过合同,它也有这个特殊的属性(来自java.lang.Object):

public boolean equals(Object obj)

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

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

JLS 4.12.5 Initial Values of Variables

  • 在创建时,每个类变量,实例变量或数组组件都使用默认值进行初始化: 对于所有引用类型,默认值为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的返回值不一定表示映射不包含键的映射;地图也可能明确地将关键字映射到nullcontainsKey操作可用于区分这两种情况。

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

相比之下,java.util.Hashtable通过不允许使用null键和值来保持简单;它的V get(Object key),如果返回null,毫不含糊地表示该键未映射。

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

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

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

它是如何在记忆中表现出来的?

在Java?你没关系。并且最好保持这种方式。


Is 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更深入;这是推荐的手表。


2
投票

instanceof是一个特殊值,不是任何类的实例。以下程序说明了这一点:

null

1
投票

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。


0
投票

在我看来,在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"); } } }


0
投票

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

http://en.wikipedia.org/wiki/SQL

在这种情况下,初始化语句声明变量“x”。 “x”存储字符串引用。它在这里是空的。首先,null不是有效的对象实例,因此没有为其分配内存。它只是一个值,表示对象引用当前不是指对象。


0
投票

简短而精确的答案,可以从JLS正式回答您的所有问题:

3.10.7。 Null Literal

null类型有一个值,null引用,由null literal null表示,它由ASCII字符组成。

null文字始终为null类型。

仅分配分配给null的类型的引用。您没有为引用分配任何值(对象)。这种分配特定于JVM将花费多少引用以及将分配哪个内存区域。


28
投票

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实现中都表示为零机器地址/指针。)


13
投票

什么是null?

没什么。

null是什么的实例?

不,因为它不是什么它不能是任何事情的例子。

null属于什么集合?

没有任何设定

它是如何在记忆中表现出来的?

如果有一些参考指向它:

Object o=new Object();

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

现在o=null;

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


8
投票

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


6
投票

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

也许可以看看

null : Java Glossary


5
投票

Java中的空(tm)

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

    0

要么:

    0L

要么:

    ((void*)0)

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

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


4
投票

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

4
投票

字节代表

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。


3
投票

null是特殊价值,它不是任何事实。显然,它不能是null的任何东西。

© www.soinside.com 2019 - 2024. All rights reserved.