1

我对我的 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() 中的这些内存问题?

4

3 回答 3

8

可能更清楚地说,在 Java 中,对象引用是按值传递的

所以 B 获得了对 List 的引用(这是一个值)的副本,而不是List 本身的副本。

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

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

于 2012-11-23T23:56:50.480 回答
3

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

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

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

于 2012-11-24T00:02:25.780 回答
1

Java 是按值传递的,该死!

但是,您只能访问对对象的引用。从这个意义上说,您正在通过 value 传递 Object 引用

于 2012-11-23T23:59:57.327 回答