java 由于在构建器模式中使用泛型,lambda表达式中的返回类型错误

bhmjp9jg  于 5个月前  发布在  Java
关注(0)|答案(1)|浏览(38)

我编写了以下构建器(简化版):

public static final class Builder<T extends SigEvents> {
    private Class<T> sigEventsType;
    private BiFunction<T, MessageExtractor, SigEventsEmitter<T>> emitterMapper;

    public Builder<T> forEmitter(@Nonnull Class<T> emitterType, @Nonnull BiFunction<T, MessageExtractor, SigEventsEmitter<T>> emitterMapper) {
        this.sigEventsType = emitterType;
        this.emitterMapper = emitterMapper;
        return this;
    }

    public SigEventsEmitter<T> buildEmitter() {
        //do some stuff which end up setting sigEventLogger and sink
        return emitterMapper.apply(sigEventLogger, sink);
    }

}

字符串
现在我尝试使用它来初始化JSFSigEventsEmitter的示例,它被声明为:

public final class JSFSigEventsEmitter extends SigEventsEmitter<JSFCoreSigEvents> {

    public JSFSigEventsEmitter(@Nonnull MessageExtractor messageExtractor, @Nonnull JSFCoreSigEvents emitter) {
        super(emitter, messageExtractor);
    }
}


.其中:

  • SigEventsEmitter被参数化为:public class SigEventsEmitter<T extends SigEvents> {
  • JSFCoreSigEventspublic interface JSFCoreSigEvents extends CoreSigEvents,它本身是public interface CoreSigEvents extends SigEvents,这是我的构建器的基本接口

在给定的上下文中,当我尝试使用构建器时:

SigEventsEmitter<JSFCoreSigEvents> sigEventEmitter = SigEventFactory.newSigEventEmitterBuilder()
            .forEmitter(JSFCoreSigEvents.class, ((jsfCoreSigEvents, messageExtractor) -> new JSFSigEventsEmitter(messageExtractor, (JSFCoreSigEvents) jsfCoreSigEvents)))
            .buildEmitter();


.我在lambda表达式的返回中得到一个错误,具体来说:Bad return type in lambda expression: JSFSigEventsEmitter cannot be converted to SigEventsEmitter<SigEvents>
我知道这是因为类型擦除,但我不明白为什么,尤其是如何修复设计。
我的forEmitter中的TT extends SigEvents的具体类型,我将其传递为JSFCoreSigEvents.class,而BiFunction的返回值应该是SigEventsEmitter<JSFCoreSigEvents>,这是我的JSFSigEventsEmitter的情况。
P.S.整个需求是能够在不相互依赖的模块之间使用这个工厂,这就是为什么我需要建立一个通用的SigEventsSigEventsEmitter合同,可以在模块之间使用,并通过这个构建器构建。

krugob8w

krugob8w1#

假设newSigEventEmitterBuilder是一个返回Builder<T>的泛型方法,编译器错误是由Java无法正确推断T是什么引起的。您希望T按照变量类型的建议是JSFCoreSigEvents,但推断只是产生其边界SigEvents作为结果。
Java没有看到这一点,因为newSigEventEmitterBuilder是调用链中的第一个。当推断链中最后一个调用的类型参数时,该语言只考虑目标类型(例如,您正在分配的变量的类型)。
解决这个问题的一个简单方法是显式地指定类型参数:

SigEventFactory.<JSFCoreSigEvents>newSigEventEmitterBuilder()
    // and so on...

字符串
这在其他情况下经常发生,你会把泛型方法链接在一起,比如Lombok's @BuilderComparator.comparing等。

相关问题