4

我有一个通用类,它需要能够克隆参数类型的对象。下面是一个非常简单的例子。编译器声称来自 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 设计者认为合理化其缺点等同于没有缺点的另一种情况?

4

3 回答 3

6

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

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

这里唯一保留完整功能的真正解决方案是使用反射来访问方法并绕过访问修饰符。另一种方法是编写您自己的MyCloneable接口,该接口上声明了一个公共 clone()方法;如果您只传入自己的域类,这可能会起作用,但这意味着您不能在外部类(例如java.util.Stringor java.util.ArrayList)上使用它,因为您不能强制它们实现您的接口。

根据对链接问题的回答,这是一个非常可疑的设计。

于 2011-03-22T16:58:59.820 回答
3

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

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

static public <T extends Cloneable> 
T clone(T obj)
    return (T) clone.invoke(obj);
于 2011-03-22T22:19:11.477 回答
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;
}
于 2013-02-08T10:54:20.720 回答