Вопрос об интервью: Объекты, имеющие право на сборку "мусора"

Дайте следующий код:

class A {
    Boolean b;
    A easyMethod(A a){
        a = null;
        return a;
    }
    public static void main(String [] args){
        A a1 = new A();
        A a2 = new A();
        A a3 = new A();
        a3 = a1.easyMethod(a2);
        a1 = null;
        // Some other code 
    }
}

Вопрос состоит в том, сколько объектов имеет право на сборку "мусора" прямо прежде // Some other code.

Затем корректный ответ (по крайней мере это - ответ интервьюера): 2 - булевская переменная b потому что это - обертка и a1 .

Можно ли понравиться мне, объясняют меня почему a2 и a3 разве существо не собрано "мусор"?

БОЛЕЕ ПОЗДНЕЕ РЕДАКТИРОВАНИЕ:

  • Хорошо, я думаю, что получаю его теперь. Это немного сбивало с толку сначала, но теперь я уверен, что интервьюер был неправ. Моя начальная ошибка состояла в том, что сначала я не полагал, что Java является передачей значением только, таким образом, невозможно сделать a2 пустой указатель из функции, которые берут "a2" в качестве параметра, потому что это a2 является на самом деле копией a2.
  • Часть с булевской переменной b была действительно довольно очевидна.

Спасибо за ответ я отправлю некоторый отклик интервью после этого :).

18
задан Andrei Ciobanu 21 July 2010 в 14:27
поделиться

6 ответов

Предполагая, что go должен быть easyMethod , он работает следующим образом

class A {
    Boolean b;
    A easyMethod(A a){
        a = null; // the reference to a2 was passed in, but is set to null
                  // a2 is not set to null - this copy of a reference is!
        return a; // null is returned
    }
    public static void main(String [] args){
        A a1 = new A(); // 1 obj
        A a2 = new A(); // 2 obj
        A a3 = new A(); // 3 obj
        a3 = a1.go(a2); // a3 set to null and flagged for GC - see above for why
        a1 = null; // so far, a1 and a3 have been set to null and flagged
        // Some other code 
    }
}

Два объекта имеют право на сборку мусора (a1 и a3). b не потому, что это всего лишь ссылка на null. Логическое значение никогда не создавалось.

Чтобы обойти бессмысленные тонкости того, что // может быть другим кодом , я вместо этого предлагаю переформулировать вопрос следующим образом:

Prdict и поясняю следующий результат:

class A {
    int i;
    A(int i) { this.i = i; }
    public String toString() { return ""+i; }
    A go(A a){
        a = null; // the reference to a2 was passed in, but is set to null
                  // a2 is not set to null - this copy of a reference is!
        return a; // null is returned
    }
    public static void main(String [] args){
        A a1 = new A(1); // 1 obj
        A a2 = new A(2); // 2 obj
        A a3 = new A(3); // 3 obj
        a3 = a1.go(a2); // a3 set to null and flagged for GC - see above for why
        a1 = null; // so far, a1 and a3 have been set to null and flagged

        test(a1);
        test(a2);
        test(a3);

    }
    static void test(A a) {
        try { System.out.println(a); } 
        catch(Exception e) { System.out.println((String)null); }
    }
}

И вывод:

c:\files\j>javac A.java

c:\files\j>java A
null
2
null

Далее следует, что на тот момент a1 и a3 имели право на сборку мусора, а a2 - нет.

Урок из этого вопроса состоит в том, что «Передача ссылки на объект методу и установка этой ссылки на null не приводит к обнулению исходной ссылки». Это знание, которое интервьюер пытался проверить.

19
ответ дан 30 November 2019 в 06:35
поделиться

Для исходного референта a2 это фактически полностью зависит от того, что происходит в «каком-то другом коде». Если «какой-то другой код» не использует a2 или a3, то исходный объект a2 имеет право на сборку мусора.

Это потому, что среда выполнения не должна заботиться о лексической области видимости. Ему просто нужно знать, что на объект больше нельзя ссылаться. Следовательно, если «какой-то другой код» не использует a2 или a3, объект, на который они указывают , больше никогда не сможет ссылаться , и поэтому уже доступен для сборки мусора.

7
ответ дан 30 November 2019 в 06:35
поделиться

При условии, что a1.go(a2) на самом деле должно быть a1.easyMethod(a2), ответ действительно 2, но не те, которые вы перечислили. Как верно заметил Божо, b не инициализирован, поэтому он не ссылается ни на какой объект. Два объекта, подлежащие сборке мусора в момент комментария, это объекты, на которые изначально ссылаются a1 и a3.

a1, очевидно, обнуляется, а a3 переназначается на возвращаемое значение a1.easyMethod(a2), которое равно нулю. Однако вызов метода не затрагивает a2, поскольку Java передает по значению, поэтому в метод передается только копия ссылки a2. Даже если копия установлена в null, это не влияет на значение исходной a2.

7
ответ дан 30 November 2019 в 06:35
поделиться

Прежде всего, интервьюер ошибается насчет логического значения - этот код не создает такого объекта, поэтому собирать мусор нечего.

Неверно говорить о переменных , таких как b и a2 , как о собираемых мусором. Сборщиком мусора подлежат объекты, а не переменные. Если переменная в области видимости ссылается на объект, она не может быть обработана сборщиком мусора. Проще говоря, сборщиком мусора может быть произведен сборщик мусора только тогда, когда на объект больше не ссылается какая-либо переменная.

Итак, у нас есть три экземпляра A, создаваемых в этом коде. Они начинаются с ссылки a1 и т. Д., Но поскольку ссылки на переменные меняются, я буду ссылаться на экземпляры объектов как A1, A2 и A3. Поскольку вы не показали определение метода go , я предполагаю, что он предназначен для вызова easyMethod .

Поскольку переменной a1 присвоено значение null, ничего не указывает на экземпляр A1, поэтому он может быть собран с помощью сборщика мусора.

Поскольку переменная a2 никогда не переназначается (присвоение в easyMethod не влияет на исходную переменную), экземпляр A2 не может быть обработан сборщиком мусора.

Поскольку easyMethod всегда возвращает null и a3 назначается результат этого метода, ничего не указывает на экземпляр A3, поэтому он также может быть собран с помощью сборщика мусора.

5
ответ дан 30 November 2019 в 06:35
поделиться

Не могли бы вы объяснить мне, почему a2 и a3 не собираются в мусор ?

Потому что a2 и a3 не являются объектами. Это переменные. Переменные не собираются по той простой причине, что они не могут быть распределены.

5
ответ дан 30 November 2019 в 06:35
поделиться

Ваш вопрос довольно запутанный.

Сборщик мусора работает с объектами, а не с переменными. Поэтому, когда вы говорите, что a2 имеет право на сборку мусора, это ничего не значит. Вы должны сказать, что объект, на который указывает a2 в строке N, имеет право на сборку мусора в строке N + M.

В вашем примере создается только 3 объекта. Это первый экземпляр create A и последний экземпляр create A, которые имеют право на сборщик мусора.

2
ответ дан 30 November 2019 в 06:35
поделиться
Другие вопросы по тегам:

Похожие вопросы: