Java:将引用设置为null不会影响对象

kar*_*ays 5 java null garbage-collection reference

我有一个简单的问题.在下面的代码中,为什么s3的值仍然打印,尽管之前我将它设置为null.似乎gargbage收集器不会被调用.

public class Test {
    public static void main(String[] args) {
         String s1 = "abc", s2 = "def", s3 = "ghj";

         String sarr[] = {s1, s2, s3};
         s3 = null;

         System.gc(); 

         for(int i = 0; i < sarr.length; i++) {
             System.out.print(sarr[i] + " "); //prints abc def ghj
         }
    }
 }
Run Code Online (Sandbox Code Playgroud)

任何想法将不胜感激.

Jon*_*eet 11

当你写:

// Moved [] to make it more idiomatic
String[] sarr = {s1, s2, s3};
Run Code Online (Sandbox Code Playgroud)

副本的值s1,s2以及s3(其参考文献,没有对象)到阵列.语句执行后,变量完全独立于数组.改变任何的价值s1,s2,s3变量来指向不同的字符串都不会影响数组的内容.

它与其他作业完全相同,例如

string x = "hello";
string y = x;
x = null; // Doesn't affect y
Run Code Online (Sandbox Code Playgroud)

和方法参数.

请注意,垃圾收集部分在这里是一个红色鲱鱼 - 虽然显然理解这对于理解垃圾收集很重要,但事实并非如此.重点是了解:

  • 的值s1,s2s3与该阵列的元件的引用,而不是对象.
  • 创建数组时会复制这些值,因此之后更改变量不会产生任何影响

现在,为了进一步举例,请考虑:

StringBuilder sb = new StringBuilder("Hello");
StringBuilder[] array = { sb };

sb.append(" world");
System.out.println(array[0]);
Run Code Online (Sandbox Code Playgroud)

这将打印的"Hello world"因为在这里我们只得到了一个StringBuilder 对象,这既sbarray[0]参考.更改该对象的数据(与更改sb引用不同的对象不同)会使更改可见,但是您可以使用它.这就像我把我家的地址给两个人 - 如果其中一个人把我的房子涂成红色,另一个人也会看到它.


Ant*_*ram 9

您已重新分配s3以指向其他内容(null),但数组内的引用仍指向原始值("ghj").

s3不是指向数组位置的常量指针.的值s3(所述参考到字符串值"GHJ")被复制到阵列.变量本身没有连接,可以自由更改以引用另一个String对象,而与您对数组内容的操作无关.