【问题标题】:Nested Casting using Class.cast() Method使用 Class.cast() 方法进行嵌套转换
【发布时间】:2014-03-11 15:25:30
【问题描述】:

我有一个Person 类,它实现了Cloneable。然后我有对象po 引用Person 对象。我正在尝试将一个克隆到另一个中,并发现以下工作:

Object p = new Person("Heather");
Object o = ((Person)p).clone();

(我必须使用该强制转换,因为 clone() 在 Object 中受到保护。我使用它在 Person 中调用 clone()。)

我需要知道的是如何使用Class.cast() 执行上述转换。我知道如何投射一次,它会是这样的:

Object o = p.getClass().cast(p);

但是我如何以这种方式进行嵌套转换示例。 (我需要知道,因为在这个项目中,我并不总是知道要转换到哪个类,但我会知道该类是 Cloneable。)

我试过了…… ((可克隆)p).clone() ...但这不起作用。 clone()方法是Object类中的受保护方法,而接口Cloneable没有clone()方法,所以编译器无法识别。

我已经到处寻找答案,但在任何地方都找不到。感谢您的帮助。

【问题讨论】:

  • 如果你知道它们都是可克隆类型,而你只是想克隆它们,我不明白你为什么不能使用 Object o = ((Cloneable)p)。克隆();。多态性FTW!
  • Class.cast 所做的只是对对象执行强制转换检查操作,以确保它是该类的实例。然后它把它留给编译器(它可能会执行另一个演员检查)来做它的通用踢踏舞。
  • 很遗憾地说 ((Cloneable)p).clone() 没有用。 clone() 是 Object 上的受保护方法,它不在接口 Cloneable 中,因此编译器无法识别它。还有其他想法吗?
  • 也许用您自己的支持clone() 方法的接口包装Cloneable
  • “嵌套铸造”是什么意思???

标签: java class casting clone


【解决方案1】:

在代码中使用clone() 是不寻常的(我从未使用过它,也从未见过它像那样明确使用过)。

用于制作副本的常用模式是copy constructor,例如:

public class Person {
    private String name;
    public Person(String name) {
       this.name = name;
    }

    // Copy constructor
    public Person(Person person) {
        this(person.name);
    }
}

源对象的重要字段的值用于初始化新对象的字段值。

【讨论】:

    【解决方案2】:

    由于克隆的工作方式,这有点困难。正如您所注意到的,clone 几乎是一个受保护的方法,因此您需要在编译时使用一个类来调用它。解决此问题的一种方法是声明一个为其分配公共访问权限的接口:

    public interface PublicCloneable
    extends Cloneable {
        public Object clone();
    }
    

    然后实现它而不是 Cloneable。然后您可以转换为 PublicCloneable 来调用克隆。这可以正常工作,但它仍然带有克隆的所有正常问题。

    创建一个复制构造函数是克隆的一个很好的替代方法,如果你在编译时不知道类,你可以创建一个通过反射调用它的方法:

    static Object reflectionCopy(Object obj) {
        try {
            Class<?> cls = obj.getClass();
            Constructor<?> ctor = cls.getConstructor(cls);
            return ctor.newInstance(obj);
        } catch(Exception e) {
            return obj;
        }
    }
    

    getClass 始终返回 Class&lt;?&gt;,因此如果您不介意未经检查的演员表,也可以将其设为通用。)

    您在这里遇到的情况可能表明您需要考虑您的设计。就我个人而言,这听起来像是通用工厂可能具有优势的情况。

    基本上是这样的:

    public interface Copier<T> {
        public T createCopy(T obj);
    }
    
    public class PersonCopier
    implements Copier<Person> {
        @Override
        public Person createCopy(Person person) {
            return new Person(person.getName());
        }
    }
    
    public static <T> T doStuffInvolvingCopy(T inObject, Copier<T> copier) {
        ...
    
        T copy = copier.createCopy(inObject);
    
        ...
    
        return copy;
    }
    

    你可以这样称呼

    doStuffInvolvingCopy(new Person("Heather"), new PersonCopier());
    

    或者也许让工厂在某个地方注册,这样它们就不需要被传递。

    工厂很好,因为它们不使用克隆,也不使用反射。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-04-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-09
      • 2014-07-18
      相关资源
      最近更新 更多