【问题标题】:Java Heap and Pass By ValueJava 堆和按值传递
【发布时间】:2012-11-12 06:54:36
【问题描述】:

我对我的 Java 程序如何分配内存感到有些困惑。以下是我的程序中的典型情况。我在一个类的堆上创建了一个对象,我将它传递给其他类中的其他函数。

public class A {
    private List<Integer> list = new ArrayList<Integer>();

    public A() {
        for(int i = 0; i < 100; i++)
            list.add(i);
    }

    public void foo() {
        B b = new B();
        b.bar(this.list);
    }
}

public class B {
    A a = new A();

    public int bar(List<Integer> list) {
        list.add(-1);
        return list.size();
    }

    public int getSize() {
        List<Integer> list = a.list;
        return a.size();
    }
}

我的问题是关于如何使用内存。当 A 的列表被传递给 B.bar() 时,内存是否被复制? Java 是按值传递的,所以我假设 B.bar() 函数现在包含列表的副本,该列表也分配在堆上?或者它是否复制列表并将其放入堆栈?还是列表完全重复?同样,B.getSize() 中的这些内存问题适用于什么?

【问题讨论】:

    标签: java memory heap-memory pass-by-value


    【解决方案1】:

    在 Java 中,object references are passed by value 可能更清楚地说。

    所以 B 获得了列表的 reference(它是一个值)的副本,而不是 List 本身的副本

    您可以通过让 B 修改列表(通过添加或删除某些内容)并观察 A 的列表也发生变化(即它是同一个列表)来轻松地向自己证明这一点。

    但是,如果您更改 B 对 List 的引用(通过创建并分配一个新 List 给它),A 的引用不会改变。

    【讨论】:

    • 谢谢。我想我只是对按值传递感到困惑,从不知道该值实际上是一个引用。
    【解决方案2】:

    Java 是按值传递的,但表达式或变量的值始终是原始值或引用。反过来,引用要么是 null,要么是指向某个对象的指针。

    在您的情况下:private List&lt;Integer&gt; list = new ArrayList&lt;Integer&gt;(); 将 list 声明为具有引用类型,并使其值成为指向新分配的 ArrayList 对象的指针。

    当您使用list 作为实际参数时,例如在b.bar(this.list); 调用中,b.bar 中的正式参数列表会使用该指针的副本进行初始化。也就是说,bar 的形式参数指向与 A 创建的相同的 ArrayList 对象。不会复制 ArrayList 对象。

    【讨论】:

      【解决方案3】:

      Java is pass-by-value, dammit!

      但是,您只能访问对对象的引用。从这个意义上说,您是在按值传递对象引用

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-03-15
        • 2013-12-02
        • 2015-11-26
        • 1970-01-01
        • 2014-08-23
        • 2015-05-23
        • 2016-11-28
        相关资源
        最近更新 更多