接口类型变量的Java克隆

时间:2012-09-19 20:25:41

标签: java interface clone

我有点像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不是任何可能的Collection中的公共方法。但是,在我想要使用它的任何具体类中,我想告诉编译器。

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

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

谢谢!

3 个答案:

答案 0 :(得分: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。你可能只想重新抛出你得到的任何异常。

答案 1 :(得分:2)

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

  1. 在您的项目中加入commons-lang
  2. 使用ObjectUtils.clone() / ObjectUtils.cloneIfPossible()(不是强类型但合理安全)。
  3. 无论如何,使用commons-lang并不是一个坏主意,因为它包含很多实用程序“应该在JRE”类和方法中,并且它是相当标准的东西。

答案 2 :(得分:0)

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

这将创建一个浅表副本。