代码之家  ›  专栏  ›  技术社区  ›  Soner from The Ottoman Empire

指定before/after::运算符的泛型方法引用类型

  •  17
  • Soner from The Ottoman Empire  · 技术社区  · 7 年前

    以下方法引用之间的区别是什么,

    BiPredicate<List<String>,String> contains1 = List<String>::contains;
    
    BiPredicate<List<String>,String> contains2 = List::<String>contains;
    
    BiPredicate<List<String>,String> contains3 = List<String>::<String>contains;
    

    3 回复  |  直到 7 年前
        1
  •  14
  •   Andy Turner    7 年前

    首先,这叫做 ( in the official Oracle Tutorial )或者 类型参数 (在 JLS Sec 15.12 )而且您可以有效地帮助编译器处理此类构造。

    一个例子:

    private static void test(Callable<Object> call) {
    
    }
    
    private static void test(Runnable run) {
    
    }
    
    static class Gen<T> {
    
    }
    

    test(Gen::new); (这将失败,无所谓为什么),但关键是您添加了 类型见证 来帮助编译器,这样就可以工作了

    test(Gen<String>::new);
    

    List<String> ,您已经为目标类型添加了类型见证- List 也就是说,在第二种情况下,为方法添加一个 contains -但它不是一般的,所以被忽略了。

        2
  •  5
  •   Oleksandr Pyrohov Andreas    7 年前

    BiPredicate<List<String>, String> contains2 = List::<String>contains;
    

    <String> 是非泛型的类型参数 List.contains 方法 1个

    在以下时间:

    BiPredicate<List<String>, String> contains1 = List<String>::contains;
    

    <字符串> List .


    JLS §15.12.2.1 :

    非泛型方法可能潜在地适用于调用 提供显式类型参数的。在这种情况下,类型

        3
  •  4
  •   Jacob G.    7 年前

    以下是Intellij告诉我的关于他们的事情:

    BiPredicate<List<String>, String> contains1 = List<String>::contains;
    

    BiPredicate<List<String>, String> contains2 = List::<String>contains;
    

    如果你把它们分成各自的lambda函数,我相信你会看到以下内容:

    BiPredicate<List<String>, String> contains1 = (List<String> strings, String o) -> strings.contains(o);
    BiPredicate<List<String>, String> contains2 = (strings, o) -> strings.<String>contains(o);
    

    我们知道, (List<String> strings, String o) (strings, o) <String> 在第二行不需要 String#contains