如何实现Child实例转型为ParentA/ParentB父类实例,未调用属性设为null?
问题描述
我定义了如下类结构(仅作概念验证,暂不考虑构造函数初始化等其他方案):
public class Child{ String testVar1; } public class ParentA extends Child{ String testVar2; } public class ParentB extends Child{ Boolean testVar3; }
然后编写了创建实例的方法:
public Child createChild(){ return new Child("testString"); } // 被调用的方法 public ParentA createParentA(){ return (ParentA) createChild(); } public ParentB createParentB(){ return (ParentB) createChild(); }
这段代码执行失败,因为无法通过子类实例转型得到父类实例。我想要的效果是生成的父类对象中,继承自Child的属性正常赋值,父类自己的属性自动设为null,比如:
{ testVar1 = "hello", testVar2 = null }
我尝试过用泛型方法实现,但写法不正确:
public <T> T createChild(Class<T> parentClass){ return (T) new Child("testString"); } // 被调用的方法 public ParentA createParentA(){ return createChild(ParentA.class); } public ParentB createParentB(){ return createChild(ParentB.class); }
请问有没有直接将子类实例转型为父类类型的方法?
核心原因
你写的代码报错的本质是:Java的类型转换只是语法层面的类型校验,不是实例的“升级”。
- 继承关系里,ParentA是Child的父类,ParentA的实例可以向下转型为Child(因为父类包含子类的所有属性);
- 但反过来,Child实例本身没有ParentA的
testVar2成员变量,JVM不可能凭空把Child对象转换成ParentA对象——这完全违背了继承的逻辑:子类是父类的扩展,父类拥有子类的全部属性,子类却不具备父类的额外属性。
可行实现方案
方案1:反射创建父类实例并复制子类属性
通过反射先创建父类的实例(此时父类自有属性默认是null),再把Child实例的属性复制到父类实例中:
public <T> T createParent(Class<T> parentClass) throws Exception { // 创建父类实例,自有属性默认初始化null T parentInstance = parentClass.getDeclaredConstructor().newInstance(); // 创建Child实例并赋值 Child child = new Child("testString"); // 复制Child的属性到父类实例 Field[] childFields = Child.class.getDeclaredFields(); for (Field field : childFields) { field.setAccessible(true); Object value = field.get(child); // 父类继承了Child的属性,必然存在对应字段 Field parentField = parentClass.getDeclaredField(field.getName()); parentField.setAccessible(true); parentField.set(parentInstance, value); } return parentInstance; } // 调用方式 public ParentA createParentA() throws Exception { return createParent(ParentA.class); } public ParentB createParentB() throws Exception { return createParent(ParentB.class); }
方案2:用Bean工具类简化属性复制
如果项目里有Spring或Apache Commons这类工具包,可以直接用BeanUtils复制属性,省去手动反射的代码:
// 以Spring的BeanUtils为例,Apache的用法类似 import org.springframework.beans.BeanUtils; public <T> T createParent(Class<T> parentClass) throws Exception { T parentInstance = parentClass.getDeclaredConstructor().newInstance(); Child child = new Child("testString"); BeanUtils.copyProperties(child, parentInstance); return parentInstance; }
方案3:重构类结构(最合理的方案)
如果允许调整类的继承关系,把Child作为父类,ParentA、ParentB作为子类,这才是Java继承的正确用法,直接创建父类实例即可满足需求:
// 重构后的类结构 public class Child { String testVar1; public Child(String testVar1) { this.testVar1 = testVar1; } } public class ParentA extends Child { String testVar2; public ParentA(String testVar1) { super(testVar1); } } public class ParentB extends Child { Boolean testVar3; public ParentB(String testVar1) { super(testVar1); } } // 调用方法 public ParentA createParentA() { return new ParentA("testString"); } public ParentB createParentB() { return new ParentB("testString"); }
这样创建的ParentA实例中,testVar1被赋值,testVar2默认是null,完全符合你的需求。
内容的提问来源于stack exchange,提问作者Jason Chan
相关产品推荐
相关产品推荐

