当一个对象只被定义时会发生什么?

3
我想知道在定义但未初始化对象时,内存级别会发生什么。
例如:
public class MainClass {
 public static void main (String[] args){
  Object foo;
 }
}

foo指向一个内存空间吗?这种行为在不同的编程语言之间会改变吗?

提前感谢。

编辑:我知道当使用对象时,它将指向null,但我想知道在对象被定义但尚未实例化后会发生什么。 在这种情况下,是否有对内存的引用?


3
这里只有一个变量,没有对象。 - ernest_k
在Java中,你只是得到一个指向"nothing"的引用。没有对象。然而,在C++中,例如,在这种情况下你得到一个真正的对象。这是为了回答你问题的第二部分。 - Robert Kock
方法内部没有任何修饰符的变量是在堆栈上创建的。 - SPlatten
简单总结一下:在Java中,如果将Object foo;用作成员变量,它将被初始化为null。如果在方法中使用,你必须自己初始化foo,否则代码可能无法正常运行。C++处理方式略有不同。在C++中,无论Object foo;放在哪里,都会调用默认构造函数。 - Tobias Brösamle
3个回答

4
我想知道在定义但未初始化对象时,内存级别会发生什么。
假设我们在这里谈论的是Java。
首先,我必须更正您不正确的描述。(出于即将变得明显的原因...)
这不是“定义一个对象”。而是“声明一个变量”。标识符foo表示一个“变量”。由于变量的类型(在本例中)为Object,它是引用类型,因此变量可以包含对Java对象或null的引用。
foo是否指向内存空间?
答案有点复杂。
如果变量已初始化,则它将指向某个对象或包含null。
如果变量未初始化,则取决于我们正在讨论的变量类型:
对于类的字段(静态或实例),未显式初始化的变量将被默认初始化为null。
对于参数或捕获变量的变量,Java语言语义确保变量始终初始化...所以这是无关紧要的。
对于局部变量,JLS没有说在给它赋值之前它包含什么。你可以说该值是不确定的。然而,JLS(以及运行时,JVM的类文件验证器)确保程序不能使用处于不确定状态的局部变量。(在Java代码中读取尚未明确定义的变量是编译错误。)因此,变量实际上包含什么并不重要。
请注意,在纯Java1中,不可能访问包含未由赋值或初始化设置的值的变量。Java语言规范不允许,JVM规范也不允许。变量永远无法观察到包含随机内存地址的情况。
这种行为在不同的编程语言之间是否会改变?
嗯...是的。例如,在C和C ++中,程序可能使用未初始化的指针变量的值。随后发生的行为是未指定的。

正如你所说,在Java中,对象更像是引用。正如也提到的那样,Java对象最好用C++中的指针来描述。但为了完整起见,在C++中你不必创建一个指针。只需声明Object foo;,C++将调用默认构造函数。 - Tobias Brösamle
@TobiasBrösamle - 我并没有尝试解释C或C++声明与Java之间的所有差异。那将是一个不同的问题(而且太宽泛了!)。 - Stephen C

3

在Java中,你可以将对象变量视为指针。默认情况下,它们指向null,只有指针本身被分配(例如,在堆栈上分配8个字节)。

你可以通过分配该对象并将其赋值给变量来使它指向实际的对象实例:

Object foo; // points to nothing (and may not be used)

foo.toString(); // compile error: The local variable obj may not have been initialized

foo = new Object(); // points to an instance of a new Object

foo = null; // again points to nothing, but is now initialized

foo.toString(); // will compile, but throw NullPointerException at run time

这与C或C++根本不同,其中Object foo;实际上是在堆栈上分配的本地对象。Java从不在堆栈上分配对象,只有原始类型或指针。


2
在Java中,当foo在类中定义时,它将指向"null",而当它在函数中定义时,它将指向空。

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