我编写了以下构建器(简化版):
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> {
- 类
JSFCoreSigEvents
是public 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
中的T
是T extends SigEvents
的具体类型,我将其传递为JSFCoreSigEvents.class
,而BiFunction
的返回值应该是SigEventsEmitter<JSFCoreSigEvents>
,这是我的JSFSigEventsEmitter
的情况。
P.S.整个需求是能够在不相互依赖的模块之间使用这个工厂,这就是为什么我需要建立一个通用的SigEvents
和SigEventsEmitter
合同,可以在模块之间使用,并通过这个构建器构建。
1条答案
按热度按时间krugob8w1#
假设
newSigEventEmitterBuilder
是一个返回Builder<T>
的泛型方法,编译器错误是由Java无法正确推断T
是什么引起的。您希望T
按照变量类型的建议是JSFCoreSigEvents
,但推断只是产生其边界SigEvents
作为结果。Java没有看到这一点,因为
newSigEventEmitterBuilder
是调用链中的第一个。当推断链中最后一个调用的类型参数时,该语言只考虑目标类型(例如,您正在分配的变量的类型)。解决这个问题的一个简单方法是显式地指定类型参数:
字符串
这在其他情况下经常发生,你会把泛型方法链接在一起,比如Lombok's
@Builder
,Comparator.comparing
等。