sjngm
sjngm

Reputation: 12861

Lambda and Generics: Why Does This Compile?

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

Answers (1)

Boris the Spider
Boris the Spider

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

Related Questions