摘自Oracle的官方Java教程,请参阅question 2 here(我的样板文件)。
public static void main(String[] args) {
String[] students = new String[10];
String studentName = "Peter Smith";
students[0] = studentName;
studentName = null;
System.out.println(students[0]);
}
答案是studentName
不符合垃圾回收的条件,因为数组students
仍然引用它。但是,最后一行打印出“Peter Smith”,所以students[0]
引用studentName
似乎是错误的。有人可以解释一下吗?
答案 0 :(得分:7)
我想在图表的帮助下逐步解释。
String studentName = "Peter Smith";
在第一行之后,在String池中创建一个String,并且引用名称 studentName 指向它。
students[0] = studentName;
此时,另一个参考学生[0]指向同一个对象,如下图所示。现在有2个引用指向在内存中创建的同一个对象。
studentName = null;
在此之后, studentName 的引用将指向null,即它指向没有对象。但是学生[0]的引用仍然指向String对象(Peter Smith)创建。
显然,在第三个语句之后,一个引用指向null,但是一个引用仍然指向创建的Object。因此,该对象不符合垃圾回收的条件。
希望它有所帮助。
更新:抱歉,如果我搞乱了变量名称。但我希望你明白这一点。
答案 1 :(得分:5)
您将引用变量(studentName
和students[0]
)与它们引用的对象混淆(" Peter Smith")。 studentName
和students[0]
都引用了String
对象" Peter Smith"。一旦他们都引用" Peter Smith" - 并假设其他地方没有其他引用 - 该对象将有资格进行垃圾回收。当它们超出范围时,引用本身就会消失。
教程弄错了。没有对象studentName
。 studentName
是一个变量,它在某一点上持有对彼得史密斯"另一点是null
。类似地,students[0]
是内存位置数组中的一个元素,它包含对#34; Peter Smith"的引用。 (相同的String
对象)。该教程将变量的概念与它们引用的对象混淆。
我可能会推测他们这样做是为了避免深入了解内存使用的细节。这是一个高级主题。但他们的解释IMO引起的混乱比它预防的更多。
答案 2 :(得分:1)
据我所知,您的代码运行如下:
String[] students = new String[10];
- 创建students
数组。 students
变量现在是指向内存中对象的指针。String studentName = "Peter Smith";
- 将变量studentName
指定给值"Peter Smith"
。 studentName
变量实际上不包含名称值。students[0] = studentName;
- 为数组中的第一个元素指定值"Peter Smith"
的指针。此时
studentName
和students[0]
都指向相同的内容,但它们都不包含值本身。
studentName = null;
- 这会将引用设置为null。它没有清除底层的内存分配。System.out.println(students[0]);
- 这将打印Peter Smith
。 数组中的0
元素包含指向原始字符串对象的指针。 因为数组仍包含对"Peter Smith"
对象的引用,即使原始指针(studentName
)已设置为null
,该对象也不符合垃圾回收的条件
如果您想更多地了解Java处理值和指针的方式,这些帖子可能有所帮助:
答案 3 :(得分:1)
认为有一个物体指向一个记忆区域,其中有一个彼得史密斯"当它分配给这个对象的另一个对象时,这个第二个对象也指向这个存储单元。之后有人想要第一个对象不指向任何存储单元,但是第二个对象仍然指向仍然具有"彼得的同一个单元。史密斯"因此这就是为什么最后一行打印名称的原因。我认为很明显jvm不能删除第一个对象,因为它仍然有值,即使第二个对象没有指针地址,其他人仍然在使用它。(如果第二个指针指向一个地址,则情况并非如此) )它还在被其他人使用