1

问题: 为什么会打印出以下内容:

ChildB___Parent of ChildB
ChildB___Parent of ChildB

而不是我认为它应该打印出来的:

ChildA___Parent of ChildA
ChildB___Parent of ChildB

简短的自包含广义问题示例:

import java.util.ArrayList;
import java.util.List;

public class StackExchangeQuestion1 {
public static void main(String[] args){
   List<String[]> list = new ArrayList();   
   String[] pair = {"childID","parentID"}; //for readability this gets overwritten       

//adding values to list
   pair[0] = "ChildA";
   pair[1] = "Parent of ChildA";
   list.add(pair);

   pair[0] = "ChildB";
   pair[1] = "Parent of ChildB";
   list.add(pair);

//checking values in list
   for(int i=0;i<list.size();i++){
   pair = list.get(i); //variable reuse for readability
   System.out.println(pair[0]+"___"+pair[1]);
   }
}}//end class and main
4

3 回答 3

4

您在列表中添加了两次相同的String[]参考。因此,列表中的两个元素都指向同一个对象。因此,当您覆盖数组时,您实际上是在写入同一块内存。该列表两次引用了这段内存,因此您得到了 2 个相同的打印语句。

Java 将通过引用传递所有非原始值(这意味着它将传递一个指向非原始对象存储在内存中的位置的指针。)

如果您像这样存储整数:

int a = 10;
list.add(a);
a = 20;
list.add(a);

一切都会好的,因为a是整数,整数是原始值,原始值是按值传递的。 这意味着存储在 a 中的数据被复制到列表中,而不是a保存在内存中的点。

然而,任何类型的字符串和数组都是非原始的。

然后,要修复您的代码,您需要将 2 个单独的引用传递给您的列表:

String[] pair1 = {"ChildA","Parent of ChildA"};
String[] pare2 = {"ChildB", "Parent of ChildB"};
//adding values to list
list.add(pair1);
list.add(pair2);

编辑:

您曾在关于冗长的评论中表达了担忧。首先,我认为您的代码并不冗长。但如果你真的很关心它,这里有一种缩短它的方法:

list.add(new String[]{"ChildA","Parent of ChildA"});
list.add(new String[]{"ChildB","Parent of ChildB"});
于 2013-07-16T01:38:01.813 回答
2

因为 anArrayList存储引用,而不是对象。引用pair总是指向同一个对象;您只需将该引用添加到您的列表中两次。

于 2013-07-16T01:37:14.773 回答
0

您的字符串对象数组在这里被覆盖。您最后的更改只会反映在您的字符串中,因为列表将存储对象的引用。如果您想获得假设的输出,则每次在设置值之前创建新对象。

于 2013-07-16T01:58:29.207 回答