在java中,更新对象时会发生什么?

时间:2014-09-12 01:46:47

标签: java

假设:

1. public class GC { 
2.     private Object o; 
3.     private void doSomethingElse(Object obj) { o = obj; } 
4.     public void doSomething() { 
5.         Object o = new Object(); 
6.         doSomethingElse(o); 
7.         o = new Object(); 
8.         doSomethingElse(null); 
9.         o=null; 
10.     }
11. }          

当的doSomething方法被调用,此后线并在Object在第5行中创建变得可用于垃圾收集?

一个。 5号线
B.线6
C.线7
D. 8号线
E. 9号线
F.第10行

答案是D,解释是当第7行新的Object()不会新建一个新对象时,它只是第5行创建的对象。

我对此非常困惑,任何人都可以帮助我吗?

5 个答案:

答案 0 :(得分:1)

让我们更清楚地写一下这个名字并稍微澄清一下:

public class GC { 

  private Object o; 
  private void setObj(Object obj) { o = obj; } 
  public void doSomething() { 
     Object o = new Object(); //4
     setObj(o); 
     o = new Object(); //6
     setObj(null); //7
     o=null; 
    }
  } 

现在,想想第4行创建的对象需要多长时间才能生存: 在第5行,您将在封闭类中保存对它的引用。所以现在只要封闭类存在并且持有对它的引用,引用就不能用于GC。

在第7行调用setObj(null)后,封闭类不再保存对第4行中创建的对象的引用。唯一的o现有副本将是范围内的副本,但变量“o”no更长的是指那个初始对象,因为你已经覆盖了第6行的引用。

顺便说一句<你的例子有点难以阅读 - 一些格式化会使这更容易。

答案 1 :(得分:0)

第5行将o设置为new Object()。第7行将o设置为new Object()。每个new Object()都是一个新对象。因此,当第7行执行时,它会构造一个新对象并将其分配给oo的先前值(它是对第5行中创建的对象的引用)不再存在。因此,对象的唯一引用消失了,因此该对象有资格进行车库收集。

答案 2 :(得分:0)

答案是after line 8,因为类字段o持有对line 5

上创建的对象的引用

doSomethingElse中,您要在类字段o中存储对第5行o的引用,因此在line 8上无效之前,它将无法用于GC

答案 3 :(得分:0)

这很容易。仔细阅读。

第1行:创建类GC 第2行:创建Object类的引用(o)并且它没有初始化,因此它将被隐式构造函数初始化为null。
第3行:doSomethingElse(Object obj)方法接受任何对象并引用' o'在第2行中创建。它表示obj和o将引用相同的对象 第4行:功能开始
第5行:使用引用' o创建的新本地对象 第6行:我们将在第5行创建的对象传递到第3行的功能,该第3行将引用第2行的对象。这意味着“' o'第2行和第5行引用第5行创建的同一对象 第7行:第5行的本地引用现在引用新的Object但旧的对象无法进行垃圾收集,因为第2行仍在引用旧对象。
第8行:我们传递null,最终将传递给第2行,因此第2行现在将引用null而不是旧对象(在第5行创建),所以现在它可以被垃圾收集。这就是答案。
在第7行创建的第9行:对象可以进行垃圾回收,或者即使我们没有写第9行,因为函数在第10行结束,本地对象将自动符合垃圾回收的条件。

这有意义吗?

答案 4 :(得分:0)

是的,D是正确的。

在第5行,您宣布一个新的参考o 阴影类级参考o。阴影意味着在此方法中使用o将引用您在第5行创建的o引用,而不是在第2行创建的引用。

因此,您在第5行创建的对象最初仅由第5行创建的o引用引用。在第6行调用doSomethingElse时,您传入您创建的实例在第5行,它将保存在班级o。所以现在有两个地方知道对象;第2行的o和第5行的o

在第7行,您可以删除其中一个。方法的o现在引用一个新对象。但是,有人仍然知道在第5行创建的对象;这是在第2行创建的o引用。

在第8行,删除最后一个引用。您将第2行定义的o更改为null。现在因为没有人知道该对象,它可以被垃圾收集。

如果我们不使用阴影,这里有一个更好的例子:

1. public class GC { 
2.     private Object a; 
3.     private void doSomethingElse(Object x) { a = x; } 
4.     public void doSomething() { 
5.         Object b = new Object(); 
6.         doSomethingElse(b); 
7.         b = new Object(); 
8.         doSomethingElse(null); 
9.         b = null; 
10.     }
11. }  

这使它更清晰,功能相同。