这是我的代码的简短示例,以证明我的观点:
public class Tmp {
static class X {
void setStr(String blah) {
}
String getStr() {
return null;
}
}
public void test() {
createCheck(X::getStr, ""); // supposed to compile
createCheck(X::getStr, 123); // rather not: int isn't String
}
private <T, V> BiPredicate<T, String> createCheck(Function<T, V> func, V value) {
return new BiPredicate<T, String>() {
@Override
public boolean test(T t, String ref) {
assertThat(func.apply(t))
.as(ref)
.isEqualTo(value);
return true;
}
};
}
}
恕我直言,编译器应该看到V
中的createCheck()
应该来自getter-function String
,这就是为什么它应该抱怨int。或者相反。
那为什么要编译?
答案 0 :(得分:7)
您的签名是:
private <T, V> BiPredicate<T, String> createCheck(Function<T, V> func, V value) {
您在T
或V
上没有界限,因此T
或V
的任何值都会被编译。
你返回一个BiPredicate<T, String>
,所以isEqualTo
方法接受String ref
并将其相等性与Object value
进行比较 - 这也是完全合法,因为我认为isEqualTo
需要Object
来模仿Object.equals
的行为。
在你的例子中:
createCheck(X::getStr, 123);
V
只是Object
,因为这是可以应用于String
和Integer
的最严格的类型绑定。
你的意思是:
private <T> BiPredicate<T, String> createCheck(Function<T, String> func, String value) {