0

我有点像 Java N00B,但我对克隆很困惑。

考虑以下不正确的类

class blah {
   public blah(Collection<Integer> c){
       member_collection = c.clone(); //the clone here is defensive
   }
   private final Collection<Integer> member_collection;
}

我想我想做的很清楚。

我理解为什么找不到 clone() 符号:clone 不是任何可能的集合中的公共方法。但是,在我想要使用的任何具体类中,我只想告诉编译器。

我确定我不是第一个想要克隆通用集合的人,但我看过的教程只解释了为什么你不能克隆集合,而不是如何解决这个问题。我已经尝试过使用 getClass() 和强制转换的 hacky 东西,但是这些通常需要我制作丑陋的 try-catch 块,而且很难确保一个初始化(指针 member_collection)是最终的!

我真正想做的是以某种方式将这些信息放入类型中。有没有很好的方法来做到这一点?

谢谢!

4

3 回答 3

3

你最好像这样复制:

public class Blah {
    private final Collection<Integer> collection;

    public Blah(Collection<Integer> collection) {
        this.collection = new ArrayList<Integer>(collection);
    }
}

或者像这样:

public class Blah {
    private final Collection<Integer> collection = new ArrayList<Integer>();

    public Blah(Collection<Integer> collection) {
        this.collection.addAll(collection);
    }
}

这与您正在尝试的内容相同,并保证Collection保留给定的任何顺序。

编辑:如果您绝对需要它与提供给您的实现相同并且您不想重新考虑您的设计,那么您可以做一些 hacky 反射的东西并将其放入一个static方法中。

public class Blah {
    private final Collection<Integer> collection;

    public Blah(Collection<Integer> collection) {
        this.collection = clone(collection);
    }

    @SuppressWarnings("unchecked")
    private static <T> T clone(T t) {
        try {
            Method cloneMethod = t.getClass().getDeclaredMethod("clone");
            return (T) cloneMethod.invoke(t);
        } catch (Exception ex) {
            // TODO Log ex
            return null;
        }
    }
}

必须将具体集合实现clone为公共方法,因此这应该适用于大多数集合。这将是null那些不这样做的人。您可能只想重新抛出您得到的任何异常。

于 2012-09-19T20:31:07.703 回答
2

由于您是 Java 新手,我很遗憾地告诉您,clone()JavaCloneable已损坏,依赖它们不是一个好主意。但是,如果你只是想要clone()那该死的东西,你可以:

  1. 在你的项目中包含commons-lang
  2. 使用ObjectUtils.clone()/ ObjectUtils.cloneIfPossible()(不是强类型但相当安全)。

无论如何,使用 commons-lang 并不是一个坏主意,因为它包含许多实用程序“应该在 JRE 中”类和方法,而且它是非常标准的东西。

于 2012-09-19T20:35:39.687 回答
0

你可以只写member_collection = new ArrayList<Integer>(c)

这将创建一个浅拷贝。

于 2012-09-19T20:27:18.833 回答