4 回答
TA贡献1828条经验 获得超3个赞
在第一个示例中,和MyInterface::getLength分别帮助"I am NOT an Integer"解析通用参数T和。RMyInterfaceSerializable & Comparable<? extends Serializable & Comparable<?>>
// it compiles since String is a Serializable
Function<MyInterface, Serializable> function = MyInterface::getLength;
Builder.of(MyInterface.class).with(function, "I am NOT an Integer");
MyInterface::getLength并不总是 a ,Function<MyInterface, Integer>除非您明确这么说,这会导致编译时错误,如第二个示例所示。
// it doesn't compile since String isn't an Integer
Function<MyInterface, Integer> function = MyInterface::getLength;
Builder.of(MyInterface.class).with(function, "I am NOT an Integer");
TA贡献1875条经验 获得超3个赞
类型推断在这里发挥了作用。R
考虑方法签名中的泛型:
<R> Builder<T> with(Function<T, R> getter, R returnValue)
在所列情况中:
Builder.of(MyInterface.class).with(MyInterface::getLength, "I am NOT an Integer");
的类型R
被成功推断为
Serializable, Comparable<? extends Serializable & Comparable<?>>
并且 aString
确实通过这种类型暗示,因此编译成功。
要显式指定 的类型R
并找出不兼容性,只需将代码行更改为:
Builder.of(MyInterface.class).<Integer>with(MyInterface::getLength, "not valid");
TA贡献1839条经验 获得超15个赞
这是因为你的泛型类型参数R
可以被推断为 Object,即以下编译:
Builder.of(MyInterface.class).with((Function<MyInterface, Object>) MyInterface::getLength, "I am NOT an Integer");
TA贡献1772条经验 获得超6个赞
这个答案基于其他答案,这些答案解释了为什么它不能按预期工作。
解决方案
下面的代码通过将双函数“with”拆分为两个连贯函数“with”和“returning”来解决该问题:
class Builder<T> {
...
class BuilderMethod<R> {
final Function<T, R> getter;
BuilderMethod(Function<T, R> getter) {
this.getter = getter;
}
Builder<T> returning(R returnValue) {
return Builder.this.with(getter, returnValue);
}
}
<R> BuilderMethod<R> with(Function<T, R> getter) {
return new BuilderMethod<>(getter);
}
...
}
MyInterface z = Builder.of(MyInterface.class).with(MyInterface::getLength).returning(1L).with(MyInterface::getNullLength).returning(null).build();
System.out.println("length:" + z.getLength());
// YIPPIE COMPILATION ERRROR:
// The method returning(Long) in the type BuilderExample.Builder<BuilderExample.MyInterface>.BuilderMethod<Long> is not applicable for the arguments (String)
MyInterface zz = Builder.of(MyInterface.class).with(MyInterface::getLength).returning("NOT A NUMBER").build();
System.out.println("length:" + zz.getLength());
(有点陌生)
添加回答
举报