2012-03-07 4 views
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 -----------| 

потому что assignements ассоциативно справа налево.

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

Может ли кто-нибудь объяснить это иначе? Thanks

+0

Два момента: во-первых, ваша вторая диаграмма должна иметь «O2 -> O1 -> null». Во-вторых, другим объектом, подходящим для gc, является исходный экземпляр 'A', назначенный' c' в 'A c = new A();'. Предположительно, вы знали это, но он не упоминался, поэтому я подумал, что упомянул об этом. :) –

ответ

6

Он начинается справа налево. Выполняется первый new A() и создается новый объект. Затем ему присваивается поле aob другого нового объекта A. Наконец d ссылается на свойство aob. Это означает, что второй объект A имеет право на сбор мусора.

Это как:

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

Но secondA объект создается рядный, так что нет ссылки на него, и он имеет право на сбор мусора.

+0

A d = новый A(). Aob = new A(); ---- будет таким же, как --- A d = новый A(); новый A(). Aob = d; – Joe

0

В этом примере, что бы вы ожидали?

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

бы d быть экземпляр a или экземпляр b?

Вы ожидали бы, что это будет отличаться только потому, что вы создаете объекты inline?

В этом примере, безусловно, d должен быть объектом b, и поэтому объект a не ссылается и может быть собран в мусор.

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

«Новый» оператор и «.» оператор вызова метода имеет тот же приоритет, но их ассоциативное качество обратное: «новое» является право-ассоциативным и «.» лево-ассоциативный.

Таким образом, компилятор сначала применяет новый оператор к «правильному операнду», который находится здесь «A()» (до появления следующего операнда). Назовем новый объект b; и у нас есть:

A d = b.aob = a; 

Компилятор теперь должен применить '.' оператор сначала (поскольку «.» имеет более высокий приоритет, чем оператор «=»). Будет называть объект, переданный на «b.aob», как с:

A d = c = a; 

Наконец все, что осталось операторы присваивания и они правоассоциативные (оцениваются справа налево). Так, присваивается гр (b.aob) первой, а затем с присваивается г.