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() );
否则有人可以解释吗? 感谢
答案 0 :(得分:6)
从右到左开始。执行第一个new A()
并创建一个新对象。然后将其分配给另一个新对象aob
的字段A
。最后d
引用了属性aob
。这意味着第二个对象A
符合垃圾回收的条件。
就像:
A firstA = new A();
A secondA = new A();
secondA.aob = firstA;
A d = secondA.aob;
但secondA
对象是内联创建的,所以没有对它的引用,它有资格进行垃圾回收。
答案 1 :(得分:0)
在这个例子中你会期待什么?
A a = new A();
A b = new A();
a.aob = b;
A d = a.aob;
d
是实例a
还是实例b
?
您是否期望它因为您在线创建对象而有所不同?
在此示例中,d
必须是对象b
,因此对象a
未被引用,可以进行垃圾回收。
答案 2 :(得分:0)
A d = new A().aob = new A();
在Java中,赋值运算符是右关联的,即它们是从右到左计算的。而且,他们是最不优先的运营商集团。
因此,首先评估第二个新运算符(第二个相等的右侧),然后得到一个新的A对象;让我们说' 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;
编译器现在需要应用'。' operator first(因为'。'的优先级高于'='运算符)。我们将'b.aob'引用的对象称为 c :
A d = c = a;
最后剩下的就是赋值运算符,它们是右关联的(从右到左计算)。因此,首先将 a 分配给 c (b.aob),然后将 c 分配给 d 。