Java不安全或未经检查的表达式:克隆一个arraylist

时间:2012-01-18 04:10:27

标签: java compiler-errors type-safety

编译时我得到了未经检查的表达式错误,发现有问题的行是

ArrayList<Integer> items = (ArrayList<Integer>) this.items.clone();

我正在尝试执行对象的深层复制,因此我以上述方式克隆了对象和数组列表的属性。我该如何修复此警告?

  • 我可以使用@SuppressWarnings("unchecked"),但这只是隐藏问题(我没想到)
  • 如果我通过循环遍历所有元素来手动克隆它会慢一点我认为

这样做的正确方法是什么?

6 个答案:

答案 0 :(得分:4)

如果你的元素是整数,那么执行“深层复制”确实不是问题,因为你没有理由需要复制一个Integer对象。只需使用new ArrayList<Integer>(this.items)

但是作为参考,clone()和ArrayList复制构造函数都不会执行深层复制。这只是因为你的元素类型不需要深度复制才能满足你的需求。

答案 1 :(得分:1)

您可以使用new ArrayList<Integer>(this.items)获得相同的行为。无论哪种方式,它都是副本。

API

答案 2 :(得分:1)

整数是不可变的,所以如果你做一个深层复制并不重要。

使用java.util中的Collections实用程序类:

import java.util.Collections;
...
ArrayList<Integer> items = new ArrayList<Integer>(this.items.size());
Collections.copy(items, this.items);

答案 3 :(得分:0)

由于将泛型引入Java API时需要向后兼容性,因此在某些情况下无法使用强制转换和@SuppressWarnings("unchecked")

另外,请参阅here,了解谨慎使用clone()用法的原因:它执行浅拷贝,对于大写字母来说很好,但对于对象很危险。

答案 4 :(得分:0)

您已经说过您正在尝试进行深层复制,但正如here所述,我怀疑您是否能够使用clone()来做到这一点。所以,就像其他海报所说的那样,使用clone()是一种更危险的方法,而你却无法获得你一直在寻找的深层拷贝。

答案 5 :(得分:0)

正如其他人所指出的,克隆ArrayList并不克隆其元素。如果你想要对内容进行深层复制,那就有一个巧妙的技巧:序列化和反序列化数组。 (这是有效的,因为ArrayListInteger都实现了Serializable。)但是,这并没有消除抑制未经检查的转换警告的需要。

// Write the object out to a byte array
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(bos);
out.writeObject(this.items);
byte[] bytes = bos.toByteArray();

// Retrieve an input stream from the byte array and read
// a copy of the object back in.
ObjectInputStream in = new ObjectInputStream(
    new ByteArrayInputStream(bytes));
ArrayList<Integer> items = (ArrayList<Integer>) in.readObject();

如果可以将整个对象声明为Serializable,则可以使用此对象而不是克隆操作来进行深层复制。另请参阅this article,以避免将字节复制出ByteArrayOutputStream的费用。