Lambda和Generics:为什么编译?

时间:2016-08-08 06:58:22

标签: java generics lambda

这是我的代码的简短示例,以证明我的观点:

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。或者相反。

那为什么要编译?

1 个答案:

答案 0 :(得分:7)

您的签名是:

private <T, V> BiPredicate<T, String> createCheck(Function<T, V> func, V value) {

您在TV上没有界限,因此TV的任何值都会被编译。

返回一个BiPredicate<T, String>,所以isEqualTo方法接受String ref并将其相等性与Object value进行比较 - 这也是完全合法,因为我认为isEqualTo需要Object来模仿Object.equals的行为。

在你的例子中:

createCheck(X::getStr, 123);

V只是Object,因为这是可以应用于StringInteger的最严格的类型绑定。

你的意思是:

private <T> BiPredicate<T, String> createCheck(Function<T, String> func, String value) {