当前位置: 代码迷 >> 综合 >> [java8]深入浅出-方法引用
  详细解决方案

[java8]深入浅出-方法引用

热度:49   发布时间:2023-12-24 02:45:38.0

无论明日,有多落魄,至少今天,没有蹉跎。 《人性的优点》

一、背景

java8是一个跨越式的版本更新,首次把函数当做一个"值"(以等值)来进行传递、动态生成、赋值。而不是看做类、接口(二等值)一个层次的东西。

编程语言的整个目的在于操作之,这些值被叫做一等值。编程语言中的其他结构有助与表示值的架构,但在程序执行期间不能传递因此是二等值。

1.1. 设计原因

lambda表达式在java8的函数式编程中起到了关键作用,而方法引用则是对lamda的一个有力补充。

  1. 对lambda的简化: 如果只是简单的调用了某个方法,可以直接使用方法引用进行替换。
  2. 更直观: 相对于lambda表达式,方法引用因为没有参数列表而显得更为精炼易读。

1.2. 使用注意

在java中方法的声明包括6个方面:修饰符、返回值、方法名、方法参数、异常列表、方法体。使用方法引用时:

  1. 修饰符要复合条件(访问不到的方法自然方法引用也不可用)
  2. 确保方法签名的匹配( 方法签名包含返回值和方法参数)
  3. 确保异常列表的兼容。(要求被引用的方法比需要的方法异常列表更小)

二、方法引用的分类

方法引用可以分为四类: 指向静态方法的、指向lambda表达式中变量的实例方法的、指向外部对象的实例方法的、构造函数的。

下图表示"两种实例方法的方法引用区别":

image-20201230165143238

如下的代码演示了四种方法引用的区别:

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* */
}

参考文档

  1. https://docs.oracle.com/javase/tutorial/java/javaOO/methods.html
  2. https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html
  3. Java 8 之方法引用
    在这里插入图片描述
  相关解决方案