有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

接口类型变量上的Java克隆

我有点像JavaN00B,但我对克隆非常困惑

考虑以下不正确的类

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()和casting的hacky功能,但这些功能通常需要我制作难看的try-catch块,而且很难确保只有一个初始化(指针成员集合)是最终的

我真正想做的是以某种方式将这些信息输入到类型中。有什么好办法吗

谢谢


共 (3) 个答案

  1. # 1 楼答案

    由于您是一名Java新手,我很抱歉地告诉您,Java中的clone()Cloneable已损坏,依赖它们不是一个好主意。然而,如果你只是想clone()这该死的东西,你可以:

    1. 在你的项目中加入commons-lang
    2. 利用ObjectUtils.clone()/ObjectUtils.cloneIfPossible()(不是强类型,但相当安全)

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

  2. # 2 楼答案

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

    这将创建一个浅拷贝

  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的任何顺序都被保留

    Edit:如果你绝对需要它与给你的实现相同,并且你不想重新思考你的设计,那么你可以做一些黑客反射的东西,并把它放在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。你可能只想重新播放你得到的任何异常