使用StringBuffer进行别名

时间:2016-07-26 11:21:58

标签: java

我正在运行此代码:

public class testttt {
public static void main(String[] args){
    ArrayList<StringBuffer> listOne = new ArrayList <StringBuffer>();
       listOne.add(new StringBuffer("One"));
       listOne.add(new StringBuffer("Two"));
       listOne.add(new StringBuffer("Three"));

    ArrayList <StringBuffer> listTwo = new ArrayList <StringBuffer>(listOne);
       listOne.add(new StringBuffer("Four"));
       for (StringBuffer str : listTwo) {
          str.append("2");
       } 

    System.out.println("List One: " + listOne);
    System.out.println("List Two: " + listTwo);

}
}

我想通过在初始化listTwo时使用“new ArrayList”声明,我会创建一个独立于listOne的独特数组。但是,输出是:

List One: [One2, Two2, Three2, Four]
List Two: [One2, Two2, Three2]

我怀疑listTwo初始化只复制了listOne的引用,但我认为它本来是由“new ArrayList”部分处理的。

非常感谢任何解释!

4 个答案:

答案 0 :(得分:1)

listOne构造使用listTwo,您说:&#34;请创建一个新列表,然后将第一个列表中的所有元素复制到第二个列表中#34;

当然,java正在做&#34; call-by-value&#34;。这意味着:&#34;复制&#34;并不意味着创建新的StringBuffers。这意味着两个列表都包含对相同 StringBuffer对象的引用。

因此,当您迭代第二个列表并修改第二个列表的成员时,您也会在第一个列表中看到效果。

所以,&#34;真实&#34;答案是:始终了解您正在使用的概念; &#34;真实&#34;这里的消息不是解释;但是作为程序员的一个核心部分是关于你编写的代码非常精确这一事实,并且真正理解你投入的每一点声明你的代码。一切都有一定的意义;如果你不了解它们,你的代码将保持令人惊讶的#34;你。

答案 1 :(得分:1)

首先创建一个包含StringBuffer实例的List(listOne)。

然后创建另一个包含StringBuffer的相同实例的List(listTwo)。但是,这是一个不同的列表。

然后你向listOne添加一个额外的元素。您只需更改listOne, listTwo。

然后更改listTwo中的每个StringBuffer实例。由于listOne和listTwo包含相同的StringBuffer实例,因此在listOne中也可以看到此更改。

注意:您没有将StringBuffer实例的副本放入listTwo,而是引用相同的对象!

答案 2 :(得分:1)

构造函数和其他方法执行浅拷贝。正如this回答中提到的那样,

浅拷贝尽可能少复制。它尝试创建对同一个旧对象的引用,因此它创建了一个集合结构的副本,而不是元素。使用浅表副本,两个集合共享各个元素。

而Deep会复制所有内容并创建重复项。它复制了原始集合中复制的所有元素。

如果要创建深层副本,可以使用Collections实用程序类。

ArrayList <StringBuffer> listTwo = new ArrayList <StringBuffer>(listOne.size());
Collections.copy(listTwo , listOne);

答案 3 :(得分:0)

当您使用ArrayList的复制构造函数时,您将告诉新列表复制旧列表的元素。实际存储在Java中的集合是 references ,您可以获得所谓的&#34;浅拷贝&#34;:引用的副本,但是相同的共享对象。

然后,当您修改这些对象时,无论您使用哪个参考列表,这些更改都是可见的。