指定before/after :: operator的通用方法引用类型

snr*_*snr 17 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;
Run Code Online (Sandbox Code Playgroud)

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

Eug*_*ene 14

首先,这被称为类型见证(在官方Oracle教程中)或TypeArguments(在JLS Sec 15.12中),您正在有效地帮助编译器使用这样的结构.

一个例子:

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

}

private static void test(Runnable run) {

}

static class Gen<T> {

}
Run Code Online (Sandbox Code Playgroud)

并通过它调用它test(Gen::new);(这将失败,更不用说为什么),但重点是你添加一个类型见证来帮助编译器,所以这将工作

test(Gen<String>::new);
Run Code Online (Sandbox Code Playgroud)

所以当你写作时List<String>,你已经为目标类型添加了一个类型见证 - List也就是说; 在第二种情况下,您要为方法添加一个contains- 但它不是通用的,因此会被忽略.

  • @Lino官方的java教程就这么称呼它,我会坚持到那个:) (4认同)
  • 术语"类型证人"来自哪里?我在语言规范中找不到它. (3认同)
  • @AndyTurner https://docs.oracle.com/javase/tutorial/java/generics/genTypeInference.html搜索"类型见证",我并没有说它出现在`JLS`中(可能是,不确定) (3认同)
  • "见证"一词并未出现在JLS中(至少9).它们在那里简称为"TypeArguments". (2认同)

Ole*_*hov 5

在:

BiPredicate<List<String>, String> contains2 = List::<String>contains;
Run Code Online (Sandbox Code Playgroud)

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

而在:

BiPredicate<List<String>, String> contains1 = List<String>::contains;
Run Code Online (Sandbox Code Playgroud)

<String>是一个类型参数List.


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

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