如何在Java中克隆一个通用列表?

179

我有一个 ArrayList<String>,希望返回它的一个副本。 ArrayList 有一个克隆方法,其签名如下:

public Object clone()

调用这个方法之后,我该如何将返回的对象转换回ArrayList<String>

17
不,这是一个有效的问题。由于Java在运行时擦除类型信息,因此不支持“真正”的泛型,因此这些细节可能会很棘手。此外,Cloneable接口和Object.clone()方法的机制同样令人困惑。 - Tim Frey
1
好的,我主要使用C#,在这方面非常容易。如果你想让我从这个问题中删除注释,请告诉我。 - Espo
1
你可以不用留言了。我认为我的编辑已经解释清楚了我遇到的问题。 - Bill the Lizard
2
你的评论还可以,只是有点傲慢。我想很多Java开发人员必须跨越的障碍在.NET开发人员看来似乎有些愚蠢。 - Tim Frey
1
@奥斯卡,他想要克隆,而不是调用克隆命令。如果复制品并没有真正克隆,那么它可能不同。我认为这就是问题所在。这确实是一个棘手的问题。 - Rafa
显示剩余2条评论
14个回答

3
非常小心地克隆ArrayList。在Java中,克隆是浅的。这意味着它只会克隆Arraylist本身而不是其成员。因此,如果您有一个ArrayList X1并将其克隆到X2中,则对X2的任何更改也将体现在X1中,反之亦然。当您克隆时,您只会生成一个新的ArrayList,并指向原始元素相同的指针。

2
这也应该可以工作:
ArrayList<String> orig = new ArrayList<String>();
ArrayList<String> copy = (ArrayList<String>) orig.clone()

1
ArrayList first = new ArrayList ();
ArrayList copy = (ArrayList) first.clone ();

1

我不是Java专家,但我有同样的问题并尝试通过这种方法解决(假设T具有拷贝构造函数)。

 public static <T extends Object> List<T> clone(List<T> list) {
      try {
           List<T> c = list.getClass().newInstance();
           for(T t: list) {
             T copy = (T) t.getClass().getDeclaredConstructor(t.getclass()).newInstance(t);
             c.add(copy);
           }
           return c;
      } catch(Exception e) {
           throw new RuntimeException("List cloning unsupported",e);
      }
}

不能保证 List 实现类具有公共的无参构造函数。例如,由 Array.asListList.ofList.subList 返回的 List 可能没有这个构造函数。 - Tom Hawtin - tackline

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接