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

如何编写无需强制类型转换的泛型方法返回自类型函数

问题:如何在Java自类型模式下避免强制类型转换?

说实话,我甚至不确定原标题是否合理,希望以下代码能说明问题。

package what.ever.you.like;

import java.util.function.UnaryOperator;

class SelfTypeTemplates {

    public static <SELF extends AbstractSelfType> UnaryOperator<SELF> simpleBound() {
        return self -> self;
    }

    public static <SELF extends AbstractSelfType<SELF>> UnaryOperator<SELF> boundWithGenericType() {
        return self -> self;
    }
}

class ConcreteSelfType extends AbstractSelfType<ConcreteSelfType> {

    public ConcreteSelfType() {
        super(ConcreteSelfType.class);
    }

    public ConcreteSelfType applySimpleBound() {
        // How to get rid of the type cast?
        return (ConcreteSelfType) SelfTypeTemplates.simpleBound().apply(this);
    }

    public ConcreteSelfType applyBoundWithGenericType() {
        // Compile error because `this` is ConcreteSelfType, but required is SELF
        return SelfTypeTemplates.boundWithGenericType().apply(this);
    }
}

class AbstractSelfType<SELF extends AbstractSelfType<SELF>> {
    protected final SELF myself;

    protected AbstractSelfType(final Class<?> type) {
        this.myself = (SELF) type.cast(this);
    }
}

我的问题出在applySimpleBound()和applyBoundWithGenericType()这两个方法上:

  • 前者可正常编译,但需要显式强制类型转换,这正是我想要消除的;
  • 后者无法编译,因为apply(this)需要SELF类型,但传入的是ConcreteSelfType。

请问如何定义SelfTypeTemplates中的方法签名,使其返回UnaryOperator<SELF>,让客户端代码(如ConcreteSelfType)调用返回函数的apply(this)时无需强制类型转换?我尝试过调整泛型的不同边界和返回类型,但未找到无需强转的可行方案。


解决方案

调整SelfTypeTemplates的方法签名

核心思路是给编译器提供足够的类型推导依据,让它能明确绑定SELF的具体类型。以下是两种可行方案:

方案1:传入Class对象作为类型标记

class SelfTypeTemplates {
    public static <SELF extends AbstractSelfType<SELF>> UnaryOperator<SELF> typedBound(Class<SELF> type) {
        return self -> self;
    }
}

方案2:通过dummy参数推导类型

class SelfTypeTemplates {
    public static <SELF extends AbstractSelfType<SELF>> UnaryOperator<SELF> boundWithInference(SELF dummy) {
        return self -> self;
    }
}

客户端代码调用示例

修改ConcreteSelfType中的方法,无需强制类型转换即可编译通过:

class ConcreteSelfType extends AbstractSelfType<ConcreteSelfType> {

    public ConcreteSelfType() {
        super(ConcreteSelfType.class);
    }

    public ConcreteSelfType applyTypedBound() {
        // 传入Class对象让编译器推导SELF类型
        return SelfTypeTemplates.typedBound(ConcreteSelfType.class).apply(this);
    }

    public ConcreteSelfType applyBoundWithInference() {
        // 传入this作为dummy参数,编译器自动推导SELF类型
        return SelfTypeTemplates.boundWithInference(this).apply(this);
    }
}

原理说明

  • 原simpleBound()的泛型约束仅限定SELF extends AbstractSelfType,缺少递归自类型绑定,编译器无法确定返回的UnaryOperator的具体类型,因此必须强转。
  • 原boundWithGenericType()没有提供类型推导的入口,编译器无法将ConcreteSelfType与方法的SELF类型关联,导致参数类型不匹配。
  • 调整后的方法通过显式类型标记或参数推导,让编译器明确SELF的具体类型,既保证了类型安全,又消除了强制类型转换的需求。

额外优化:简化父类构造

可以通过反射优化AbstractSelfType,避免子类手动传入Class对象:

class AbstractSelfType<SELF extends AbstractSelfType<SELF>> {
    protected final SELF myself;

    @SuppressWarnings("unchecked")
    protected AbstractSelfType() {
        // 利用反射获取实际子类类型,省去手动传参
        this.myself = (SELF) this;
    }
}

内容的提问来源于stack exchange,提问作者Tob

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 05:15:24