如何通过泛型从父类Person创建指定母国的子类实例?
解决方案:基于母国动态创建对应Person子类
1. 完善子类构造,固化母国值
先把子类的母国值在构造方法里固定,避免重复设置:
@Data public class Norwegian extends Person { public Norwegian() { setMotherland(Country.NORWAY); // 若Country是字符串类型,直接传"Norway" } } @Data public class Portuguese extends Person { public Portuguese() { setMotherland(Country.PORTUGAL); } }
2. 实现映射工厂类
创建工厂类,通过母国和子类的映射关系,动态生成对应子类实例:
public class CitizenFactory { // 维护母国到子类的映射表 private static final Map<Country, Class<? extends Person>> CITIZEN_TYPE_MAP = Map.of( Country.NORWAY, Norwegian.class, Country.PORTUGAL, Portuguese.class ); @SuppressWarnings("unchecked") public static <T extends Person> T createCitizen(Person basePerson) throws Exception { Class<? extends Person> targetClass = CITIZEN_TYPE_MAP.get(basePerson.getMotherland()); if (targetClass == null) { throw new IllegalArgumentException("无法识别的母国:" + basePerson.getMotherland()); } // 创建子类实例 T citizen = (T) targetClass.getDeclaredConstructor().newInstance(); // 复制原Person的属性(如果属性多,用BeanUtils更高效) citizen.setName(basePerson.getName()); // 母国已在子类构造中设置,无需重复赋值 return citizen; } }
如果属性数量多,推荐用Spring的BeanUtils.copyProperties(basePerson, citizen)替代手动赋值,减少冗余代码。
3. 修改泛型服务方法
调整getCitizen方法,结合工厂实现动态返回对应子类:
@Inject @RestClient PopulationInfoClient populationInfoClient; public <T extends Person> T getCitizen(String personId) throws Exception { Person rawPerson = this.populationInfoClient.search(personId); return CitizenFactory.createCitizen(rawPerson); }
补充说明
- 如果
Country是字符串而非枚举,只需把映射表的key改成字符串(比如"Norway")即可适配。 - 异常处理可根据业务需求调整,比如返回默认
Person实例、抛出自定义业务异常等。
内容的提问来源于stack exchange,提问作者Ekaterina Anisova
相关产品推荐
相关产品推荐

