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

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

一、背景

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

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

1.1. 设计原因

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

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

1.2. 使用注意

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

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

二、方法引用的分类

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

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

[java8]深入浅出-方法引用_第1张图片

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

public class FunctionRefSt {
     
    // 静态方法
    public static int length(String str) {
     
        return str.length();
    }
    // 实例方法
    public int lengthIns(String str) {
     
        return str.length();
    }
    // 四种引用的展示
    @Test
    public 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);
  /**
  输出: 
  kkk
  ll
  oo
  2
  2
  3
  /*
}

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);
    /*输出:
    goodBye
    hello
    world
    * */
}

参考文档

  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 之方法引用

你可能感兴趣的:(java,java,编程语言,lambda,stream,深入浅出)