在Java中将对象转换为其子类

时间:2016-04-06 12:13:18

标签: java oop class-hierarchy

这不是一个常规问题,请听我的解释。

我有一个班级Cat的对象。如何将其转换为子类Animal a = new Animal(); Cat c = (Cat) a; ?像这样:

Animal

当然,我知道不可能直接从Cat投射到Cat。但我不想手动创建新的Animal并将字段从DI复制到其中。因为有时候我有很多需要转换的类层次结构。我怎样才能以一般方式解决它?

3 个答案:

答案 0 :(得分:3)

忽略这样一个事实,在你的例子中你要反转原样关系(如“苹果是一个水果”与“一个水果是一个苹果”) - 这在某种程度上是没有意义的。

但是让我们想象一下,你必须让一个potate 看起来像一个苹果。所以你要做的就是把所有的果肉都拼成苹果(我在这里使用水果的例子,因为动物会变得有点乱)。 这可以称为代理或包装。

这两种技术都可以在java中静态或动态完成。

静态:包装器:

  • 创建新类,即VeggiAppleWrapper
  • 让它扩展Apple(所以它包装的东西看起来像苹果)
  • 定义一个接受另一种类型的构造函数(即Potato)
  • 实现/覆盖常用的方法并将调用委托给包装对象
  • 实现抛出UnsupportedOperationException的所有其他方法

动态:代理:

  • 您必须至少为目标类型定义一个接口(即interface Apple
  • 使用Proxy
  • 创建代理实例
  • 使用已实现接口列表中的Apple接口
  • 为您执行转发MethodInvocationHandler,类似于Wrapper,但使用Reflection
  • 将代理转换为Apple

使用Java动态代理的替代方法是代码生成库,例如CGLibJavaassist,它们在运行时生成目标类型的子类,它与包装器基本相同,但是像代理一样实现

为了将值从动物复制到cat实例(因为动物是超类,一些字段应该是常见的),你也可以使用反射api

for(Field f : Animal.class.getDeclaredFields()) { 
  f.setAccessible(true)
  f.set(cat, f.get(animal));
} 

这只是一个简单的例子,没有异常处理,也没有考虑Animal的超类字段(getDeclaredFields只检索 this 类的字段)。

答案 1 :(得分:2)

如何在子类中创建复制构造函数?

Animal

super(animal)类中声明这样的构造函数,只需使用googleMapEngine.load(getClass().getResource("/googleLondonMap.html").toExternalForm()); 从任何子类传递一个控件,您将在其中定义自定义逻辑。

答案 2 :(得分:-1)

我认为你做对了

Animal animal = new Animal();
Cat cat = new Cat();

public void foo(){
  animal = cat; //works because Animal is parent class
  cat = (Cat) animal; //you cast Animal to Cat like as parent to child
}

查看https://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html

我希望它会有所帮助