在Java中,null是堆上存在的对象吗?

3
在Java中,null是堆上的一个现有对象吗?
我试图理解未初始化的局部变量(编译错误)和使用null初始化的变量之间的区别(可编译)。

2
这是一个问题还是陈述,或者说这是什么东西,我甚至不知道。 - Matti Virkkunen
这是一个问题吗?我知道它有一个问号,但我不确定。 - Chuck Vose
2
问题的意图很明确,尽管语言有些别扭。 - Steven Sudit
如果你在问这个问题,你可能会认为Java变量的值是对象。它们不是。Null不是一个对象 - 任何其他Java变量的值也不是对象。 - Andy Thomas
@Tom - 啊。那么 x = null; 是一个线索。:) 即使 null 在运行时引用了某个对象,它也不能帮助编译时的明确赋值检查。 - Andy Thomas
显示剩余3条评论
5个回答

7

非常好的链接!谢谢!(在选择正确答案之前,我想听取更多意见) - The Student
1
我没有给这个本来正确的答案点赞的唯一原因是因为我认为目标是在这里回答并链接支持文档和参考资料。这只是一个链接。 - Steven Sudit
3
@Steven:这个问题(原来的提问)有些边缘化,而且已经被关闭过一次。我只是想指引提问者朝正确的方向去。 - Robert Harvey
除非您认为它仍然处于边缘地带,否则没有解释的链接仍然是不合适的。我不会点踩,但也不会点赞。 - Steven Sudit

3

这个问题突出了作用域明确赋值之间的联系。如果您在调试器中逐行执行下面的代码,您可以看到以下几个特点:

  1. 没有断点;i 不在作用域内。
  2. i 在作用域内,但“当前上下文中未知变量”。
  3. 引用i已被赋值,并且它的值为null
  4. 引用i的值为1,在第4行后将被递增。

清单:

Integer i;
i = null;
i = Integer.valueOf(1);
i++;

补充:

那么,null和未初始化之间有什么区别?

明确赋值 之前,局部变量的值是不可访问的;任何尝试访问该值的操作都会在编译时被拒绝。一旦明确赋值,即使是 null,该值也可以被访问。这是 Java 中的一个关键安全特性。在某些语言中,未初始化变量 可能会引用先前进程留下的内存中的值。

补充:帧的局部变量 在初始化之前的内容是未指定的。字节码验证器 防止访问未初始化的内存的字节码,但是可能存在 异常字节码


好的,但在初始化之前,实际上该内存位置中有什么?它是否被清零? - Steven Sudit
我相信这个过程是实现特定的;更多内容请参考上文。 - trashgod

3
或者,为了节省您的点击,答案是否定的,它不是一个对象。 null意味着没有引用任何对象。

@Peter 但您必须同意,null 不完全是一个值.. 它是“没有值”字面量。因此,null 可能存在于某个地方.. - The Student
@Tom Brito:无论如何,“null”都保证是无效的。在C和C++中,它通常由一个所有位为零的指针表示。从技术上讲,它指向某个地方,但通常是受保护的内存,因此您无法使用它所指向的内容。 - David Thornley
@Peter:我知道这不是Java,但在C#中,未初始化的引用值实际上包含null。这是因为CLR不愿意分配内存块并将其交出而不将它们清零。我怀疑在JVM中也是如此。 - Steven Sudit
@Steven:可能是的,尽管很难验证,因为Java不允许您使用未初始化的局部变量。但是类中的字段会被初始化为它们的默认值(null/false/0)。 - Peter Štibraný
@Peter:有趣。堆可能会初始化为零,但编译器确保在使用变量之前显式初始化变量,从而使栈保持清洁。 - Steven Sudit
显示剩余4条评论

0

一个尚未被赋值的本地变量,很可能也指向 null。我不是 JVM 专家,但这似乎是合乎逻辑的选择。

因此编译器会检查你是否已经给变量赋值。除此之外没有任何区别。在运行时,尚未初始化的本地变量将被赋值为 null。


它并没有“指向”任何东西。拥有为空,而不是指向某个东西。 - user207421
我完全不同意。这是原始问题的本质。答案是错误的。 - user207421

0

Null不是一个对象。实际上,它是一个对象的相反,这就是为什么你不能对指向null的引用进行方法调用的原因。如果你真的想知道null是什么,你可以把它看作是类似于零的东西。事实上,指向null的引用不会占用任何额外的内存,即零。它没有值,所以它是一个不引用任何对象的引用。

在Java中,你必须在使用变量之前初始化它。由于历史原因,Java不希望你假设值,因此编译器强制你给它赋一个值。其中一部分原因是C语言由于没有初始化值或强制你在使用之前初始化值而导致的错误和安全问题。Java会为基本类型和实例变量初始化一些值:0、0.0、false和null等,但对于局部变量,你必须给它一个值。这是为了你自己的保护。 :-)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接