Java中如何从泛型参数C推导G,避免重复声明泛型参数?
解决方案
首先明确:Java的类型系统没有直接支持从泛型类型参数C中自动推导G并将其作为类级别的类型变量的语法,但我们可以通过两种方式实现你的需求,要么保证类型安全,要么简化类声明:
1. 保留双泛型参数(最类型安全的选择)
虽然看起来G是冗余的,但这是Java泛型的限制——要在类的方法中直接使用G作为返回类型,必须显式将其声明为类的泛型参数。这种方式完全类型安全,没有强制转换的风险:
// 保持原类声明,这是最稳妥的写法 public abstract class GameScreen<C extends Controller<G>, G extends Game> extends MPScreen { public G getGameInstance() { // 通过Controller的方法获取G实例(建议给Controller添加getGame方法) return getController().getGame(); } public abstract C getController(); } // 给Controller添加获取Game实例的方法 public abstract class Controller<G extends Game> { protected G game; public G getGame() { return game; } }
子类实现时依然需要指定两个参数,但这是Java泛型的标准用法,不会带来额外运行时开销,且能保证编译期类型检查。
2. 用泛型方法配合Controller的getGame方法(简化类声明)
如果不想在类级别声明G,可以将getGameInstance改成泛型方法,依赖Controller提供的G实例获取能力:
public abstract class GameScreen<C extends Controller<? extends Game>> extends MPScreen { // 泛型方法让编译器在调用时推导G类型 public <G extends Game> G getGameInstance() { // 转换安全,因为Controller的getGame方法返回的就是它的泛型参数G return (G) getController().getGame(); } public abstract C getController(); } // Controller同样需要添加getGame方法 public abstract class Controller<G extends Game> { protected G game; public G getGame() { return game; } }
调用getGameInstance时,编译器会自动推导返回类型,也可以显式指定:
MyGame game = gameScreen.getGameInstance(); // 或显式指定类型 MyGame game = gameScreen.<MyGame>getGameInstance();
为什么最初的通配符写法不行?
当你用Controller<? extends Game>时,这个通配符代表某个未知的Game子类,编译器无法将这个未知类型作为方法的返回类型——它无法确定你具体指的是哪个G,自然无法在getGameInstance中返回确定的G类型。
内容的提问来源于stack exchange,提问作者Slackow
相关产品推荐
相关产品推荐

