将数组元素设置为String对象时,该元素是否引用该对象?

时间:2016-02-01 17:38:10

标签: java garbage-collection

摘自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似乎是错误的。有人可以解释一下吗?

4 个答案:

答案 0 :(得分:7)

我想在图表的帮助下逐步解释。

String studentName = "Peter Smith";

在第一行之后,在String池中创建一个String,并且引用名称 studentName 指向它。

Part1

students[0] = studentName;

此时,另一个参考学生[0]指向同一个对象,如下图所示。现在有2个引用指向在内存中创建的同一个对象。

Part2

studentName = null;

在此之后, studentName 的引用将指向null,即它指向没有对象。但是学生[0]的引用仍然指向String对象(Peter Smith)创建。

enter image description here

显然,在第三个语句之后,一个引用指向null,但是一个引用仍然指向创建的Object。因此,该对象不符合垃圾回收的条件。

希望它有所帮助。

更新:抱歉,如果我搞乱了变量名称。但我希望你明白这一点。

答案 1 :(得分:5)

您将引用变量(studentNamestudents[0])与它们引用的对象混淆(" Peter Smith")。 studentNamestudents[0]都引用了String对象" Peter Smith"。一旦他们都引用" Peter Smith" - 并假设其他地方没有其他引用 - 该对象将有资格进行垃圾回收。当它们超出范围时,引用本身就会消失。

教程弄错了。没有对象studentNamestudentName是一个变量,它在某一点上持有对彼得史密斯"另一点是null。类似地,students[0]是内存位置数组中的一个元素,它包含对#34; Peter Smith"的引用。 (相同的String对象)。该教程将变量的概念与它们引用的对象混淆。

我可能会推测他们这样做是为了避免深入了解内存使用的细节。这是一个高级主题。但他们的解释IMO引起的混乱比它预防的更多。

答案 2 :(得分:1)

据我所知,您的代码运行如下:

  1. String[] students = new String[10]; - 创建students数组。 students变量现在是指向内存中对象的指针。
  2. String studentName = "Peter Smith"; - 将变量studentName指定给值"Peter Smith"studentName变量实际上不包含名称值。
  3. students[0] = studentName; - 为数组中的第一个元素指定值"Peter Smith"的指针。
  4.   

    此时studentNamestudents[0]都指向相同的内容,但它们都不包含值本身。

    1. studentName = null; - 这会将引用设置为null。它没有清除底层的内存分配。
    2. System.out.println(students[0]); - 这将打印Peter Smith数组中的0元素包含指向原始字符串对象的指针。
    3. 因为数组仍包含对"Peter Smith"对象的引用,即使原始指针(studentName)已设置为null,该对象也不符合垃圾回收的条件

      如果您想更多地了解Java处理值和指针的方式,这些帖子可能有所帮助:

答案 3 :(得分:1)

认为有一个物体指向一个记忆区域,其中有一个彼得史密斯"当它分配给这个对象的另一个对象时,这个第二个对象也指向这个存储单元。之后有人想要第一个对象不指向任何存储单元,但是第二个对象仍然指向仍然具有"彼得的同一个单元。史密斯"因此这就是为什么最后一行打印名称的原因。我认为很明显jvm不能删除第一个对象,因为它仍然有值,即使第二个对象没有指针地址,其他人仍然在使用它。(如果第二个指针指向一个地址,则情况并非如此) )它还在被其他人使用