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

Generic method reference type specifying before/after :: operator

下面的方法引用有什么区别,

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;

案例有特殊名称吗?有类似用法的例子吗?

以下是 Intellij 告诉我的关于它们的内容:

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

Explicit type arguments can be inferred

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

Type arguments are redundant for the non-generic method reference

如果将它们拆分为各自的 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 不是通用的),所以它是可以安全地假设两个方法引用是等价的。

首先,这被称为 type witness (in the official Oracle Tutorial) or TypeArguments (in the JLS Sec 15.12),您正在有效地帮助编译器进行此类构造。

一个例子:

private static void test(Callable<Object> call) {

}

private static void test(Runnable run) {

}

static class Gen<T> {

}

并通过 test(Gen::new); 调用它(这会失败,不管为什么),但关键是你添加了一个 type witness 来帮助编译器,所以这会起作用

test(Gen<String>::new);

因此,当您编写 List<String> 时,您已经为目标类型添加了类型见证 - List 即;在第二种情况下,您要为方法 contains 添加一个 - 但它不是通用的,因此将被忽略。

在:

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:

忽略类型参数

A non-generic method may be potentially applicable to an invocation that supplies explicit type arguments. In such a case, the type arguments will simply be ignored.