是Java传值吗?垃圾收集相关

时间:2017-11-09 06:19:55

标签: java garbage-collection

我有一个问题让我很困惑,

运行以下代码的第8行后,哪些对象有资格进行垃圾回收?

public class X 
{
    public static void main(String [] args) 
    {
        X x = new X();
        X x2 = m1(x);          /* Line 6 */
        X x4 = new X();
        x2 = x4;               /* Line 8 */
        doComplexStuff();
    }
    static X m1(X mx) 
    {
        mx = new X();
        return mx;
    }
}

A .X
B .x和x2
C .x和x4
d .x4

我最初的想法是只有x2被垃圾收集,因为当x2 = x4时它在第8行被引用,并且因为java是按值传递的,所以X x2 = m1(x)不会影响x。

我在这里https://www.indiabix.com/java-programming/garbage-collections/discussion-202也找到了完全相同的问题(但是选择不同),并且有些评论说x也应该被垃圾收集,这与我的想法相矛盾,现在我很困惑哪个这个问题的选择是正确的,提前谢谢。

3 个答案:

答案 0 :(得分:2)

许多人已回答x2引用的对象是垃圾收集。 下面是一个示例代码,允许您自己检查GC,此代码还演示了Java的行为:

Java通过引用操作对象,但它按值将对象引用传递给方法。

public class GCInJava 
{
     int i=0;
    String name="default";
    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        System.out.println("[GCing object referenced by: "+this.name+"]");
    }
    public static void main(String [] args) 
    {
        GCInJava x = new GCInJava();
        x.name="x";
        System.out.println("x before calling m1(): "+x);
        System.out.println("x.i before calling m1(): "+x.i);
        GCInJava x2 = m1(x);    
        System.out.println("x.i after calling m1(): "+x.i);
        System.out.println("x after calling m1(): "+x);
        System.out.println("x2.i: "+x2.i);
        GCInJava x4 = new GCInJava();
        x4.name="x4";
        x2 = x4;               
        System.gc();
        doComplexStuff();
    }
    static GCInJava m1(GCInJava mx) 
    {
        System.out.println("mx before new object: "+mx);
        mx = new GCInJava();
        mx.i=10;
        mx.name="mx/x2";
        System.out.println("mx after new object: "+mx);
        return mx;
    }
}

注意: System.gc()可能并不总是通过JVM触发垃圾回收;所以尝试运行几次代码。

示例输出(注意打印的哈希码):

  在调用m1()之前

:tests.GCInJava@64c3c749
  x.i在调用m1()之前:0   新对象之前的mx:tests.GCInJava@64c3c749
  新对象后的mx:tests.GCInJava@7150bd4d
  调用m1()后的x.i:0   调用m1()后的x:tests.GCInJava@64c3c749
  x2.i:10

     

[引用的GCing对象:mx / x2]

答案 1 :(得分:1)

我认为这不是一个特别好的问题。

首先, 变量不符合垃圾收集的条件,对象可以。 所以说x2符合GC的条件意味着什么,因为那时候我可以说mx也符合条件,因为该方法已返回。这使得它看起来好像内存中的对象多于实际对象。

这更准确

  

第12行创建的对象符合GC的条件。

此外,第5行创建的对象不符合条件,x仍在引用它。只需尝试打印x中的值。你会发现它不是空的。

答案 2 :(得分:0)

是的,你是对的。

Java是"传递值",只有mxmx = new X();被垃圾收集。

x并非垃圾收集。例如;

public class X
{
    public static void main(String [] args)
    {
        X x = new X();
        X x2 = m1(x);
        X x4 = new X();
        x2 = x4;
        doComplexStuff();
        System.out.print(x); // no problem; line 10
    }
    static X m1(X mx) 
    {
        mx = new X();
        return mx;
    }
}

如果x被垃圾收集,则第10行是错误的。事实上,事实并非如此。 因此,x不是垃圾回收