面试问题:符合垃圾回收条件的对象

2022-09-02 19:34:32

给出以下代码:

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 - 布尔值,因为它是一个包装器和。ba1

你能不能请我解释一下为什么没有被垃圾收集?a2a3

稍后编辑:

  • 好吧,我想我现在明白了。起初有点令人困惑,但现在我确信面试官错了。我最初的错误是,起初我不认为Java只是按值传递的,所以不可能从以“a2”作为参数的函数内部使a2 null,因为a2实际上是a2的副本。
  • 带有布尔b的部分确实非常明显。

感谢您的回答,我会在:)之后发送一些采访反馈。


答案 1

假设应该是这样工作的goeasyMethod

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)。 不是因为它只是对 null 的引用。从来没有制造过。bBoolean

为了绕过可能是什么的无聊微妙之处,我反而假设这个问题应该改写成以下内容:// Some other code

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有资格获得GC,而a2则没有。

从这个问题中得到的教训是,“将对象引用传递给方法并将该引用设置为 null 不会导致原始引用为 null”。这就是面试官试图测试的知识。


答案 2

提供实际上意味着,答案确实是2,但不是你列出的那些。正如Bozho正确指出的那样,它没有初始化,所以它不是指任何对象。在注释点符合垃圾回收条件的两个对象是 和 最初引用的对象。a1.go(a2)a1.easyMethod(a2)ba1a3

a1显然为空,并重新分配给 返回值为 null。但是,不受方法调用的影响,因为 Java 是按值传递的,因此仅将引用的副本传递给方法。即使副本设置为 null,也不会影响原始值。a3a1.easyMethod(a2)a2a2a2