英文:double colon,双冒号(::)运算符在Java 8中被用作方法引用(method reference),方法引用是与lambda表达式相关的一个重要特性。它提供了一种不执行方法的方法。为此,方法引用需要由兼容的函数接口组成的目标类型上下文。
Method References
You use lambda expressions to create anonymous methods. Sometimes, however, a lambda expression does nothing but call an existing method. In those cases, it’s often clearer to refer to the existing method by name. Method references enable you to do this; they are compact, easy-to-read lambda expressions for methods that already have a name.
参考oracle官网
您使用lambda表达式来创建匿名方法。然而,有时lambda表达式除了调用现有方法外什么也不做。在这些情况下,通过名称引用现有方法通常更清楚。方法引用使您能够做到这一点;它们是紧凑的、易于阅读的lambda表达式,用于已经有名称的方法。
以下是Java 8中方法引用的一些语法:
静态方法引用(static method)语法:classname::methodname 例如:User::getAge
对象的实例方法引用语法:instancename::methodname 例如:System.out::println
对象的超类方法引用语法: super::methodname
类构造器引用语法: classname::new 例如:ArrayList::new
数组构造器引用语法: typename[]::new 例如: String[]:new
现有一个类 Something
class Something {
// constructor methods
Something() {}
Something(String something) {
System.out.println(something);
}
// static methods
static String startsWith(String s) {
return String.valueOf(s.charAt(0));
}
// object methods
String endWith(String s) {
return String.valueOf(s.charAt(s.length()-1));
}
void endWith() {}
}
如何用 '::' 来访问类Something中的方法呢?先定义一个接口,因为必须要用 functional interface 来接收,否则编译错误(The target type of this expression must be a functional interface)
@FunctionalInterface
interface IConvert<F, T> {
T convert(F form);
}
(@FunctionalInterface 注解要求接口有且只有一个抽象方法,JDK中有许多类用到该注解,比如 Runnable,它只有一个 Run 方法。)
观察接口 IConvert,传参为类型 F,返回类型 T。所以,我们可以这样访问类Something的方法:
访问静态方法
// static methods
IConvert<String, String> convert = Something::startsWith;
String converted = convert.convert("123");
访问对象方法
// object methods
Something something = new Something();
IConvert<String, String> converter = something::endWith;
String converted = converter.convert("Java");
访问构造方法
// constructor methods
IConvert<String, Something> convert = Something::new;
Something something = convert.convert("constructors");
总结:我们可以把类Something中的方法static String startsWith(String s){...}、String endWith(String s){...}、Something(String something){...}看作是接口IConvert的实现,因为它们都符合接口定义的那个“模版”,有传参类型F以及返回值类型T。比如构造方法Something(String something),它传参为String类型,返回值类型为Something。注解@FunctionalInterface保证了接口有且仅有一个抽象方法,所以JDK能准确地匹配到相应方法。