指定::操作符之前/之后的通用方法引用类型

时间:2018-08-10 12:33:54

标签: java generics java-8 method-reference

以下方法参考之间有什么区别

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 个答案:

答案 0 :(得分:14)

首先,这就是类型见证人in the official Oracle Tutorial)或 TypeArguments (在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添加一个-但它不是通用的,因此将被忽略。

答案 1 :(得分:5)

在:

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

<String>是非通用List.contains方法 1 的类型参数。

在:

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

<String>List的类型参数。


1-在这种情况下,根据JLS §15.12.2.1,类型参数将被忽略:

  

非泛型方法可能适用于调用   提供显式类型参数。在这种情况下,类型   参数将被忽略。

答案 2 :(得分:4)

这是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不是通用的),因此可以安全地进行假定两个方法引用都是等效的。