无论明日,有多落魄,至少今天,没有蹉跎。 《人性的优点》
一、背景
java8是一个跨越式的版本更新,首次把函数当做一个"值"(以等值)来进行传递、动态生成、赋值。而不是看做类、接口(二等值)一个层次的东西。
编程语言的整个目的在于操作之,这些值被叫做一等值。编程语言中的其他结构有助与表示值的架构,但在程序执行期间不能传递因此是二等值。
1.1. 设计原因
lambda表达式在java8的函数式编程中起到了关键作用,而方法引用则是对lamda的一个有力补充。
- 对lambda的简化: 如果只是简单的调用了某个方法,可以直接使用方法引用进行替换。
- 更直观: 相对于lambda表达式,方法引用因为没有参数列表而显得更为精炼易读。
1.2. 使用注意
在java中方法的声明包括6个方面:修饰符、返回值、方法名、方法参数、异常列表、方法体。使用方法引用时:
- 修饰符要复合条件(访问不到的方法自然方法引用也不可用)
- 确保方法签名的匹配( 方法签名包含返回值和方法参数)
- 确保异常列表的兼容。(要求被引用的方法比需要的方法异常列表更小)
二、方法引用的分类
方法引用可以分为四类: 指向静态方法的、指向lambda表达式中变量的实例方法的、指向外部对象的实例方法的、构造函数的。
下图表示"两种实例方法的方法引用区别":
如下的代码演示了四种方法引用的区别:
public class FunctionRefSt {
// 静态方法public static int length(String str) {
return str.length();}// 实例方法public int lengthIns(String str) {
return str.length();}// 四种引用的展示@Testpublic void funcRef() {
Optional<String> opt = Optional.of("hello world");/*以下三种输出都是11*/// 静态方法引用opt.map(FunctionRefSt::length).ifPresent(System.out::println);// 内部实例方法引用opt.map(String::length).ifPresent(System.out::println);// 外部实例方法引用FunctionRefSt functionRefSt = new FunctionRefSt();opt.map(functionRefSt::lengthIns).ifPresent(System.out::println);/*构造函数引用实例*/// 利用optional避免空指针System.out.println(Optional.<List>ofNullable(null).orElseGet(/*引用了构造方法*/ArrayList::new).size());//输出0}
}
三、典型使用场景
3.1 普通使用
@Test
public void test() {
Stream.of("kkk", "ll", "o").peek(System.out::println).map(String::length).sorted(Integer::compareTo).forEach(System.out::println);/**输出: kkklloo223/* }
PS: 1. peek可以用来打日志,便于debug
3.2 看着不一致的签名不一定不匹配
- String方法的 compareTo签名 :
public int compareTo(String anotherString)
- sorted方法要求的签名:
int compare(T o1, T o2);
虽然看着像签名不一样,但因为实例方法compareTo有一个隐含的this参数,String类的compareTo()方法在实际调用的时候,第一个隐含参数总是传入this,相当于静态方法:
public static int compareTo(this, String o);
? 所以String.compareTo()方法也可作为方法引用传入:
@Test
public void comparatorString() {
Stream.of("hello", "goodBye", "world").sorted(String::compareTo).forEach(System.out::println);/*输出:goodByehelloworld* */
}
参考文档
- https://docs.oracle.com/javase/tutorial/java/javaOO/methods.html
- https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html
- Java 8 之方法引用