Reputation: 12861
This is a shortened sample of my code to prove my point:
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;
}
};
}
}
IMHO, the compiler should see that V
in createCheck()
should be String
coming from the getter-function, which is why it should complain about the int. Or the other way around.
So why does this compile?
Upvotes: 2
Views: 43
Reputation: 61148
Your signature is:
private <T, V> BiPredicate<T, String> createCheck(Function<T, V> func, V value) {
You have no bounds on T
or V
so absolutely any values of T
or V
would compile.
You return a BiPredicate<T, String>
however, so the isEqualTo
method takes the String ref
and compares its equality to the Object value
- this is also perfectly legal as I suppose isEqualTo
takes an Object
to mimic the behaviour of Object.equals
.
In your example:
createCheck(X::getStr, 123);
V
is simply Object
as that is the tightest type bound that can apply to String
and Integer
.
Did you perhaps mean:
private <T> BiPredicate<T, String> createCheck(Function<T, String> func, String value) {
Upvotes: 7