我想在 Java 中复制一个列表,我找到了一个名为 的方法clone
,它可以做到这一点,并且工作正常,但我认为我没有正确使用它,因为我在Eclipse中收到警告。
我所做的是创建一个列表,向其中添加一个整数,最后使用复制方法。
ArrayList<Integer> lista = new ArrayList<Integer>();
list.add(5);
ArrayList<Integer> listaCopiada = (ArrayList<Integer>) lista.clone();
显然有一个问题,该方法返回 a Object
,所以我不得不强制转换它,当我这样做时,它对我有用,但我收到警告。
类型安全:从 Object 到 ArrayList<Integer> 的未经检查的强制转换
我可以单击警告并查看多种解决方案,但没有一个能说服我。
提取到局部变量:
这复制了该行,然后我收到另一个相同类型的警告。
ArrayList<Integer> clone = (ArrayList<Integer>) lista.clone();
ArrayList<Integer> clone2 = clone;
ArrayList<Integer> clone1 = clone2;
ArrayList<Integer> clone21 = clone1;
ArrayList<Integer> clone11 = clone21;
提取到方法:
这使我成为一个私有函数,它内部有一行带有相同的警告。
ArrayList<Integer> listaCopiada = extracted(lista);
private static ArrayList<Integer> extracted(ArrayList<Integer> lista) {
return (ArrayList<Integer>) lista.clone();
}
当我尝试修复该警告时,我留下了一个递归函数,这对我来说似乎很不合逻辑,因为它删除了克隆部分。
private static ArrayList<Integer> extracted1(ArrayList<Integer> lista) {
return extracted1(lista);
}
在演员表周围添加括号:
这对我来说增加了一些无意义的括号,警告如下。
ArrayList<Integer> listaCopiada = ((ArrayList<Integer>) lista.clone());
我得到的建议是删除多余的括号,这又回到了以前的样子。
添加 SuppressWarnings '未选中':
这迫使我对代码使用注释,告诉我不要抛出警告。这是我不再收到警告的唯一方法,但我认为它看起来很难看。
@SuppressWarnings("unchecked")
有没有办法(如果可能是官方的或正确的)在clone
没有这样警告的情况下使用?
关于警告,删除它的唯一方法是使用
@SupressWarnings
. 发生这种情况是因为您正在转换为泛型类型。在 Java 中,没有其他方法可以转换为通用定义的对象(在这种情况下,从Object
aArrayList<Integer>
)并删除警告。@SupressWarnings
只要您知道自己在做什么,使用 没有任何问题。如果您删除了泛型,您将收到有关使用原始变量(原始类型)的另一个警告,您仍然必须添加此注释。该方法是 Java 实现原型
clone
模式的一次糟糕尝试。我说差,因为从技术上讲,它没有提供太多价值,而且只是一个浅拷贝。只有少数情况下应该调用 clone 方法,例如在数组上。对于您的情况,如果您只想要具有相同对象的新列表的浅表副本,也就是说,如果您修改新列表中的对象之一的状态,您还将看到原始列表中的状态更改(因为它们是同一个对象),那么以下内容就足够了:
如果您正在寻找深层副本,这意味着即使新列表中的对象也与原始对象不同并且每个对象都有自己的状态,您需要确保原始列表中的每个元素都是不可变的或实现的您自己的深度克隆方法,如复制构造函数、序列化/反序列化或其他。
我会避免使用
clone
. 如果你想复制列表,你可以简单地这样做:除了禁用该类型的消息之外,没有其他方法可以删除警告。
clone
它将返回一个类型的元素,Object
这是您无法修改的。另一种方法是停止使用
clone
并使用复制构造函数制作对象的副本:您可以使用该类
java.util.Collections
:或最常用的方法: