2013-09-18 4 views
3

Взятые из SCJP 6 приготовительных книг -мусора - почему c3 не имеют прав на коллекцию в этом примере (SCJP 6)

Дана:

class CardBoard { 
    Short story = 200; 
    CardBoard go(CardBoard cb) { 
     cb = null; 
     return cb; 
    } 
    public static void main(String[] args) { 
     CardBoard c1 = new CardBoard(); 
     CardBoard c2 = new CardBoard(); 
     CardBoard c3 = c1.go(c2); 
     c1 = null; 
     // do Stuff 
    } 
} 

Когда // DoStuff достигнут, сколько объектов имеют право на GC?

А. 0

Б. 1

С. 2

Д. Сборник терпит неудачу

E. Это невозможно знать

F. An исключение выбрасывается во время выполнения

Правильный ответ: C - «Только один объект CardBoard (c1) имеет право, но у него есть связанный объект Short wrapper, который также имеет право».

Мой вопрос: почему c3 не подходит для сбора?

Мои мысли -

c1.go (c2) устанавливает локальную ссылочную переменную, Cb (который является копией c2), нулевое значение, а затем возвращает сЬ, который назначен на с3. Я знаю, что ссылочная переменная для c2 сама по себе не может быть изменена в методе, а только объект за ней. Однако мне кажется, что копия ссылочной переменной cb установлена ​​в значение null и назначена на c3. Почему c3 не установлен в возвращаемый null в этом экземпляре?

+0

Хм. Я не уверен, что мне нравится говорить: «Короткая обложка тоже лишена прав». Я понимаю, что прямо сейчас объект Short ссылается на объект CardBoard. Ссылка не удаляется, пока CardBoard не получит GCed правильно? Может кто-нибудь прокомментировать это?После того, как CardBoard получит GCed, теперь Short будет eligibile, но в данный момент я не думаю, что это – Cruncher

+0

На короткий объект ссылается картонный объект, однако из-за того, что это недоступно для живой нити поскольку ссылка, которая содержит ссылку, является нулевой, она также имеет право (изолированная ссылка) – SMC

ответ

7

Нет объектов, связанных с c3. Его значение равно null, поэтому ничего не собирать.

+4

Да, если c3 был создан сначала, тогда это будет для GC – Cruncher

+0

Не удалось увидеть дерево для деревьев, спасибо Kayaman – SMC

+0

@ LinuxN00b Я думаю, что примеры SCJP обычно бесполезны. Никто в здравом уме не писал бы код, который они используют в своих примерах, и вы обычно не тратите время на размышления о том, когда объекты gc'd. – Kayaman

1

Этот «правильный» ответ SCJP является фиктивным. Правильный ответ - либо 4, либо «Невозможно знать».

Если код читается буквально («// Stuff» является просто комментарием), то объект, ранее достижимый из c2, как мертвый, так и GC, как тот, который ранее упоминался в c1, и поскольку оба те, которые сейчас недоступны, имеют объекты c1.story и c2.story, которые также будут умирать вместе с ними, в общей сложности 4 объекта имеют право на сбор.

Однако, если вещь «// Делает материал» является заполнителем для какого-либо неизвестного кода, то этот код может использовать или не использовать c2, что означает, что объект, на который указывает c2, может быть или не быть мертвым и иметь право для сбора, когда этот код будет достигнут. Поэтому, если мы не знаем, что такое «// Делать материал» на самом деле, это либо 2, либо 4, которые имеют право на участие, и нет способа узнать, что.

+0

На самом деле ссылка C2 никогда не является нулевой, копия ссылки C2 переходящий в метод c1.go (Картон c), обнуляется. Вы можете влиять на объекты за пройденными ссылочными переменными, но вы не можете изменить объект, на который ссылается исходная ссылочная переменная, из метода, который он передал в – SMC

+0

@ LinuxN00b. Гил, конечно же, не сработал с трюком «Java-pass-by-value» ; он сказал, что в момент комментария '// do stuff' последнее использование' c2' уже передано; поэтому объект, на который указывает 'c2', недоступен по определению (« нет возможных будущих вычислений, которые могли бы получить к нему доступ »). –

 Смежные вопросы

  • Нет связанных вопросов^_^