Java中的null是什么?


252

什么null

null任何事的实例吗?

null属于什么集合?

它在内存中如何表示?


yegor256。JLS中的null。“空文字。空类型具有一个值,即空引用,由空文字null表示,它由ASCII字符组成。空文字始终是空类型。” 关于文章的要点。“可变和不完整的对象”是一项功能。“缓慢失败”是一种设计能力。“计算机思维与对象思维”只是两种思维方式。“歧义语义”过于主观。“临时错误处理”是处理错误的另一种类型。空值是字面值或JLS中指定的其他任何东西,而不是好坏。
Oleksii Kyslytsyn

Answers:


310

null是否是任何实例?

不,没有类型nullinstanceof

15.20.2类型比较运算符 instanceof

RelationalExpression:
    RelationalExpression instanceof ReferenceType

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

这意味着对于任何类型的ER,对于任何E o,在那里o == nullo instanceof R永远是false


“ null”属于什么集合?

JLS 4.1类型和值的种类

还有一个特殊的null类型,即expression的类型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变量的初始值

  • 每个类变量,实例变量或数组组件在创建时均使用默认值初始化:
    • 对于所有引用类型,默认值为null

使用方法各不相同。您可以使用它来启用所谓的字段的延迟初始化,在该字段中,字段的初始值null直到实际使用为止,在该字段中将其替换为“实际”值(计算起来可能会很昂贵)。

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

public static Console console()

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

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

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

public String readLine() throws IOException

返回String包含行内容的A ,不包含任何行终止字符,或者null是否已到达流的末尾。

因此,在这里,readLine()将为instanceof String每一行返回,直到最终返回a 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不一定表示该映射不包含键的映射;否则,返回值为0 。映射也可能将键显式映射到null。该containsKey操作可用于区分这两种情况。

在这里,我们开始了解使用null如何使事情复杂化。第一条语句说,如果键未映射,null则返回。第二个声明说,即使按键映射,null被退回。

相反,java.util.Hashtable通过不允许null键和值来简化事情;其V get(Object key),如果返回null,则明确表示未映射密钥。

您可以通读其余的API,并找到在何处以及如何null使用它们。请记住,它们并不总是最佳实践示例。

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

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

它在内存中如何表示?

在Java中?不用担心 最好保持这种方式。


null好事吗?

现在这是主观的。有人说这null会导致许多程序员可以避免的错误。有人说,在NullPointerException像Java这样的流行语言中,最好使用它,因为您会因程序员错误而快速失败。有些人避免null使用Null对象模式等。

它本身是一个巨大的主题,因此最好将其讨论为对另一个问题的解答。

最后,我将引用null他自己的发明者CAR Hoare(快速成名)的报价:

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

此演示文稿视频更加深入;这是推荐的手表。


4
空引用在LISP中(如NIL)于1960年或更早存在。但是我不认为Hoare 确实试图在该报价中主张发明空引用。
斯蒂芬·C

7
Hoare没有试图要求发明空引用;他只是声称自己在特别有影响力的地方提供了这些工具。很明显,包括Java在内的许多语言都是从Algol那里获得灵感的,如果使用null引用甚至部分地是受Algol的启发或从Algol复制而来的,那么Hoare将这些成本的责任归咎于是正确的。但是,我的确感到他的估计相当低。一万亿美元可能更接近真实成本。
cjs

32

null是否是任何实例?

不。这就是为什么所有班级null instanceof X都会回来。(不要被您可以分配给类型为对象类型的变量这一事实所迷惑。严格来说,分配涉及隐式类型转换;请参见下文。)falseXnull

“ null”属于什么集合?

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

“还有一个特殊的空类型,即表达式null的类型,它没有名称。因为空类型没有名称,所以不可能声明一个空类型的变量或将其强制转换为空类型。 reference是null类型的表达式的唯一可能的值。null引用始终可以转换为任何引用类型。实际上,程序员可以忽略null类型而只是假装null只是可以是任何类型的特殊文字参考类型。” JLS 4.1

什么是null?

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

它在内存中如何表示?

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


14

什么是null?

没什么

null是否是任何实例?

不,因为它什么都不是,它不可能是任何事物的实例。

null属于哪个集合?

没有任何集合

它在内存中如何表示?

如果某些参考指向它,例如:

Object o=new Object();

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

现在 o=null;

这意味着现在o将不再指向对象的存储空间。


1
“现在o = null;这意味着现在o将不再指向对象的内存空间。” 我觉得这是垃圾收集如何工作的JAVA
Hardik米什拉

9

不,它不是任何东西的实例,instanceof将始终为false。



6

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

6

Java中的null(tm)

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

    0

要么:

    0L

要么:

    ((void*)0)

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

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


5

字节码表示

Java null具有直接的JVM支持:用于实现它的三个指令:

  • aconst_null:例如将变量设置nullObject o = null;
  • ifnullifnonnull:例如,一个对象比较null,如if (o == null)

然后,第6章“ Java虚拟机指令集”提到了null其他指令的影响:它NullPointerException为许多指令抛出了。

2.4。“引用类型和值”null以通用术语提及:

引用值也可以是特殊的空引用,即无对象的引用,此处将以空表示。空引用最初没有运行时类型,但可以强制转换为任何类型。引用类型的默认值为null。


4

null是特殊值,它不是任何实例。出于明显的原因,它不可能是instanceof任何东西。


3

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

6
该示例显示的唯一null内容不是的实例String
Sasha Chedygov

4
如果将签名更改为void f(String o),则更有意义。
Thilo

2

Java中的null与C ++中的nullptr类似/相似。

用C ++编写的程序:

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中的相同程序:

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中的null是什么吗?如果没有,那么我建议您学习C / C ++的指针,然后您将理解。

请注意,在C语言中,与C ++语言不同,未定义nullptr,但使用了NULL,也可以在C ++语言中使用NULL,但是在C ++中,nullptr不仅比NULL更可取,因为C中的NULL始终与指针相关,并且因此,在C ++中,后缀“ ptr”附加在单词的末尾,并且所有字母现在都小写,但这并不重要。

在Java中,每个非基本类型类的变量总是引用该类型或继承的对象,并且null是null类对象引用,但不是null指针,因为在Java中没有这样的东西“指针”,而是对class的引用而是使用对象,并且Java中的null与类对象引用有关,因此您也可以将其称为“ nullref”或“ nullrefobj”,但这很长,因此只需将其称为“ null”即可。

在C ++中,可以将指针和nullptr值用于可选成员/变量,即没有值的成员/变量,如果没有值,则等于nullptr,因此可以使用Java中的null。


1

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

String x = null;

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


0

在我看来,在Java中查看null的一种有趣方式是将其视为不表示没有信息的东西,而仅仅是将其分配给任何类型的引用的文字值。如果考虑是否表示没有信息,那么a1 == a2为true是没有意义的(如果它们都被分配了null值),因为它们实际上可能指向任何对象(我们只是不知道它们应该指向什么对象)...顺便说一下,null == null在Java中返回true。如果java eg例如SQL:1999,则null == null将返回unknown(SQL:1999中的布尔值可以采用三个值:true,false和unknown,但实际上,unreal在实际系统中实现为null)... http://en.wikipedia.org/wiki/SQL


0

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

3.10.7。空字面量

空类型具有一个值,即空引用,由空文字空值表示,由ASCII字符组成。

空文字始终是空类型。

仅分配分配给null的类型的引用。您没有为参考分配任何值(对象)。这种分配是特定于JVM的,它将获取多少参考以及将在哪个内存区域中分配参考。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.