如何将Cloneable类型用作Java泛型类的参数

时间:2011-03-22 16:46:53

标签: java generics cloneable

我有一个通用类,需要能够克隆参数类型的对象。下面是一个非常简单的例子。编译器声称来自Object类型的clone()不可见。

public class GenericTest<T extends Cloneable>
    {
    T obj;
    GenericTest(T t)
        {
        obj = t;
        }
    T getClone()
        {
        // "The method clone() from the type Object is not visible."
        return (T) obj.clone();
        }
    }

我不希望调用者进行克隆,因为还有其他事情需要保持对象的完整性。上面的代码只是问题的一个例子,没有我必须维护的与克隆对象相关的其他数据的噪音。

有没有办法解决这个问题,或者这是Java设计师考虑将其缺点合理化而不是没有这种情况的另一种情况?

3 个答案:

答案 0 :(得分:6)

因为该方法在protected类上标记为Object,所以通常不能在任意对象上调用此方法。我个人认为这不是一个问题(嘿,我是Object的子类,所以我应该能够调用它的受保护方法,对吗?),但编译器需要知道你是目标对象的类(或其包中)的子类,以便调用受保护的方法,这两种方法都不适用于此。

clone()方法背后的想法是支持它的类会覆盖该方法,并将其声明为public

此处保留完整功能的唯一真正解决方案是使用反射来访问方法并绕过访问修饰符。另一种方法是编写自己的MyCloneable接口,其上声明了 public clone()方法;如果您只是传递自己的域类,这可能会有效,但意味着您无法在外部类(例如java.util.Stringjava.util.ArrayList)上使用它,因为您无法强制执行他们实现你的界面。

根据linked question的答案,这是一个非常可疑的设计。

答案 1 :(得分:2)

Java的一个错误。反思是正确的方法

static Method clone = Object.class.getMethod("clone"); 

static public <T extends Cloneable> 
T clone(T obj)
    return (T) clone.invoke(obj);

答案 2 :(得分:0)

我需要克隆包含字段的POJO。做了以下工作:

public static Object clone(Object o)
{
  Object clone = null;

  try
  {
     clone = o.getClass().newInstance();
  }
  catch (InstantiationException e)
  {
     e.printStackTrace();
  }
  catch (IllegalAccessException e)
  {
     e.printStackTrace();
  }

  // Walk up the superclass hierarchy
  for (Class obj = o.getClass();
    !obj.equals(Object.class);
    obj = obj.getSuperclass())
  {
    Field[] fields = obj.getDeclaredFields();
    for (int i = 0; i < fields.length; i++)
    {
      fields[i].setAccessible(true);
      try
      {
        // for each class/suerclass, copy all fields
        // from this object to the clone
        fields[i].set(clone, fields[i].get(o));
      }
      catch (IllegalArgumentException e){}
      catch (IllegalAccessException e){}
    }
  }
  return clone;
}