2012-11-23 24 views
1

我对我的Java程序如何分配内存有点困惑。以下是我的计划中的典型情况。我在类中创建了一个对象,并将其传递给其他类中的其他函数。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()内部吗?

回答

7

在Java中可能会更清楚一点,object references are passed by value

所以B获得的参考(这是一个值)列表的副本,而不是复制的列表本身

通过让B修改列表(通过添加或删除某些内容)并观察A的列表也发生了变化(即它是相同的列表),您可以很容易地证明这一点。但是,如果您将B的引用更改为列表(通过创建并向其分配新列表),则A的引用将保持不变。

+0

谢谢。我想我只是与传递值相混淆,从不知道这个值实际上是一个参考。 –

3

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

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

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