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

发布于 2024-10-25 20:12:05 字数 499 浏览 10 评论 0原文

我有一个泛型类,需要能够克隆参数类型的对象。下面是一个非常简单的例子。编译器声称 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 设计者考虑合理化其缺点的另一种情况?

I have a generic class that needs to be able to clone objects of the parameter type. A very simple example is below. The compiler claims clone() from the type Object is not visible.

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();
        }
    }

I'd prefer not to have the caller do the cloning since there are other things that have to happen to maintain the integrity of the object. The code above is just an illustration of the problem without the noise of the other data I have to maintain related to the cloned object.

Is there a way around this or is this another one of those cases where the designers of Java consider rationalizing its shortcomings the equivalent of having none?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

人心善变 2024-11-01 20:12:05

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

clone() 方法背后的想法是,支持该方法的类将重写该方法,将其声明为 public

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

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

Because the method is marked as protected on the Object class, you cannot in general call this method on arbitrary objects. Personally I didn't think this would be a problem at first (hey, I'm a subclass of Object, so I should be able to call its protected methods, right?), but the compiler needs to know that you're a subclass of the target object's class (or in its package) in order to call protected methods, neither of which apply here.

The idea behind the clone() method is that classes which supported it would override the method, declaring it as public.

The only real solution here that preserves full functionality is to use reflection to access the method and get around the access modifiers. An alternative would be to write your own MyCloneable interface which has a public clone() method declared on it; this might work if you'll only ever be passing your own domain classes in, but means that you couldn't use it on external classes (such as java.util.String or java.util.ArrayList) since you can't force them to implement your interface.

As per answers to the linked question, this is a very dubious design.

你另情深 2024-11-01 20:12:05

Java 方面的一个错误。反思才是正确的出路

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

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

A mistake on Java's part. Reflection is the right way to go

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

static public <T extends Cloneable> 
T clone(T obj)
    return (T) clone.invoke(obj);
与君绝 2024-11-01 20:12:05

我需要克隆一个包含字段的 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;
}

I needed to clone a POJO with fields in it. What did work was the following:

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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文