以下方法参考之间有什么区别
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;
案件有特殊名称吗?有没有类似用法的例子?
答案 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
不是通用的),因此可以安全地进行假定两个方法引用都是等效的。