3
class A{
     A aob;
     public static void main(String args[]){
          A a=new A();
          A b=new A();
          A c=new A();
          a.aob=b;
          b.aob=a;
          c.aob=a.aob;
          A d=new A().aob=new A();  //tricky assignement
          c=b;                      //one object eligible GC
          c.aob=null;
          System.gc();
     }
}

有两种对象符合垃圾收集条件,但一种很难理解。

A d=new A().aob=new A();

1)这条线我认为它会做到这一点

A d = new A().aob = new A();
          ^             ^
          O1            O2

      O1 --> O2 --> null
      ^
      |
d ----| 

2)但真正在做的是这个(所以一个合格的对象)为什么会这样?

A d = new A().aob = new A();
          ^             ^
          O1            O2

      O1 --> O2 --> null
             ^
             |
d -----------| 

因为分配是从右到左关联的。

A d = ( new A().aob = new A() );

谁能解释一下?谢谢

4

3 回答 3

6

它从右到左开始。首先new A()执行并创建一个新对象。然后将其分配给aob另一个新对象的字段A。最后d是引用属性aob。这意味着第二个对象A有资格进行垃圾回收。

它像是:

A firstA = new A();
A secondA = new A();
secondA.aob = firstA;
A d = secondA.aob;

但是该secondA对象是内联创建的,因此没有对它的引用,并且它有资格进行垃圾回收。

于 2012-03-07T20:41:59.817 回答
0

在这个例子中,你会期待什么?

A a = new A();
A b = new A();
a.aob = b;
A d = a.aob;

d是实例a还是实例b

您是否会因为内联创建对象而期望它有所不同?

在这个例子中肯定d必须是 object b,所以 objecta没有被引用并且可以被垃圾收集。

于 2012-03-07T20:43:14.903 回答
0
A d = new A().aob = new A();

在Java 中,赋值运算符是右结合的,即它们是从右到左求值的。而且,它们属于最低优先级运算符组。

所以首先计算第二个新运算符(第二个相等的右边),我们得到一个新的 A 对象;让我们说'一个'。现在我们有:

new A().aob = a;

这里的诀窍是识别运算符的优先级。看看这里: http: //pages.cs.wisc.edu/~willb/cs302/spring-07/java-operator-precedence.pdf

'new' 运算符和 '.' 方法调用运算符具有相同的优先级,但它们的关联质量是相反的:'new' 是右关联的,而 '.' 是左结合的。

因此,编译器首先将 new 运算符应用于此处为“A()”的“右操作数”(在下一个操作数到位之前)。让我们称新对象b;我们有:

A d = b.aob = a;

编译器现在需要应用 '.' 运算符优先(因为 '.' 的优先级高于 '=' 运算符)。让我们将 'b.aob' 引用的对象称为c

A d = c = a;

最后剩下的就是赋值运算符,它们是右关联的(从右到左计算)。因此,首先将 a分配给c (b.aob),然后将c分配给d

于 2012-03-07T21:30:38.027 回答