You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 23:51:17