如何将抽象类子类作为方法参数,实现不同子类对象的统一初始化
解决方案
原有代码无法运行的核心原因是Java语法限制:new关键字后必须跟实际类类型,你传入的typeOfThePieceWeWantToInitialise是抽象类的实例对象,不能直接用于实例化。以下是两种可落地的实现方案:
方案1:函数式接口工厂(推荐,类型安全无额外开销)
适合Java 8及以上版本,利用构造方法引用实现,编译期即可检查参数合法性,无反射相关的性能损耗和运行时风险。
- 首先自定义匹配棋子构造方法签名的函数式接口:
// 入参、返回值完全匹配所有棋子子类的构造方法规则 @FunctionalInterface public interface PieceFactory<T extends AbstractPiece> { T create(Color color, Position position); }
- 修改
initPiece方法,接收工厂接口作为参数:
public void initPiece(Position position, Color color, PieceFactory<? extends AbstractPiece> pieceFactory) { AbstractPiece piece = pieceFactory.create(color, position); // 此处补充将棋子加入棋盘、注册管理等后续业务逻辑 }
- 调用时直接传入对应子类的构造方法引用即可:
// 初始化黑方国王 initPiece(new Position(0, 0), Color.BLACK, King::new); // 初始化白方王后 initPiece(new Position(0, 4), Color.WHITE, Queen::new); // 初始化白方车 initPiece(new Position(0, 0), Color.WHITE, Rook::new);
注意:所有棋子子类需要存在访问权限为public、入参顺序为
(Color, Position)的构造方法。
方案2:反射实现(适合需要动态传递类类型的场景)
如果业务需要传入类对象作为参数,可以用反射实现,需要手动处理运行时异常:
public void initPiece(Position position, Color color, Class<? extends AbstractPiece> pieceClass) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException { // 获取对应子类匹配参数的构造方法 Constructor<? extends AbstractPiece> constructor = pieceClass.getConstructor(Color.class, Position.class); AbstractPiece piece = constructor.newInstance(color, position); // 此处补充后续业务逻辑 }
调用时传入对应子类的Class对象即可:
initPiece(new Position(0, 0), Color.BLACK, King.class);
内容的提问来源于stack exchange,提问作者La Légende
相关产品推荐
相关产品推荐

