Java中如何在抽象类实例方法内创建子类新实例且避免样板代码
解决方案
你可以通过以下两种方案避免在每个实现类中重复编写创建实例的样板代码:
方案1:父类反射获取子类类型创建实例
利用Java对象的运行时类型特性,在抽象父类中直接获取当前实例的实际子类Class,通过反射构造新实例,子类无需额外实现任何方法:
abstract class AbstractClass { public AbstractClass newInstance() { try { // 获取当前实例的实际运行类(即对应的实现类) return getClass().getDeclaredConstructor().newInstance(); } catch (Exception e) { throw new RuntimeException("实现类缺失无参构造,无法创建实例", e); } } } class Implementation extends AbstractClass { // 不需要重写任何创建实例的方法 } // 调用逻辑和你原来的代码完全一致 class Scratch { public static void main(String[] args) { Implementation implementation = new Implementation(); AbstractClass implementedAbstractClass = implementation; AbstractClass newInstance = implementedAbstractClass.newInstance(); // 输出class Implementation,符合预期 System.out.println(newInstance.getClass()); } }
注意该方案要求所有AbstractClass的实现类必须提供无参构造,否则会在运行时抛出异常。
方案2:Supplier注入创建逻辑(编译期安全,无反射开销)
如果希望避免反射的性能开销和运行时异常风险,可以用JDK自带的Supplier函数式接口在父类中存储实例构造逻辑:
abstract class AbstractClass<T extends AbstractClass<T>> { private final Supplier<T> constructor; protected AbstractClass(Supplier<T> constructor) { this.constructor = constructor; } public T newInstance() { return constructor.get(); } } class Implementation extends AbstractClass<Implementation> { public Implementation() { // 只需要在构造函数中传入自身的构造引用即可,无需额外实现方法 super(Implementation::new); } } // 调用逻辑保持不变 class Scratch { public static void main(String[] args) { Implementation implementation = new Implementation(); AbstractClass<Implementation> implementedAbstractClass = implementation; Implementation newInstance = implementedAbstractClass.newInstance(); } }
该方案所有校验都在编译期完成,不会出现运行时构造失败的问题,性能和直接new对象完全一致。
内容的提问来源于stack exchange,提问作者CausingUnderflowsEverywhere
相关产品推荐
相关产品推荐

