Java8 教程

Java8 Lambda 方法引用

在 Lambda 表达式中,如果我们的 Lambda 表达式仅仅拥有一个已经实现的方法。例如,按钮(Button)点击时打印 event 对象信息,如下:

button.setOnAction(event -> System.out.println(event));

为了追求代码简洁,Lambda 表达式提供了一种更简单的写法,通过 “::” 符号引用方法,如下:

button.setOnAction(System.out::println);

上面代码中,表达式 System.out::println 是一个方法引用,等同于 Lambda 表达式 “event ->System.out.println(event)”。

我们再举另外一个例子,假设你希望不区分大小写地对字符串进行排序,那么可以传入下面这个方法引用:

String[] strings = {"A", "C", "D", "B"};
Arrays.sort(strings, String::compareToIgnoreCase);

什么是方法引用?

Lambda 方法引用使用一种简洁的方式来引用已存在的方法,可以在函数式编程中使用。它可以用来传递方法作为参数,或者在流式操作中使用。Lambda 方法引用使用双冒号(::)操作符来引用已存在的方法,”::“ 操作符将方法名和对象或类的名字分隔开来。主要有如下三种方式:

  • 对象::实例方法,例如:System.out::println 等同于 System.out.println(x)

  • 类::静态方法,例如:Math::pow 等同于 (x,y )-> Math.pow(x, y)

  • 类::实例方法,例如:String::compareToIgnoreCase 等同于 (x, y) -> x.compareToIgnoreCase(y)

  • this::实例方法,例如:this::equals 等同于 x ->this.equals(x)

  • super::实例方法,例如:super::equals 等同于 x -> super.equals(x)

注意:如果有多个同名的重载方法,编译器会试图从上下文中找到最匹配的一个方法。例如,有两个版本的 Math.max 方法,一个接收 int 作为参数,而另一个接收 double 类型的值。究竟会选择哪一个方法,取决于 Math.max 被转换为的函数式接口的方法参数。同 Lambda 表达式类似,方法引用也不会独立存在,它们经常被用于转换为函数式接口的实例。

方法引用示例

对象::实例方法

用于引用对象上的实例方法,下面将引用当前示例中的 sort 实例方法,如下:

package com.hxstrive.jdk8.lambda;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Demo06 {

   public static void main(String[] args) {
       Demo06 demo = new Demo06();

       List<String> list = Stream.of("One", "Two", "Three")
               // 引用对象的实例方法
               .map(demo::sort)
               .collect(Collectors.toList());
       for(String str : list) {
           System.out.println(str);
       }
   }

   private String sort(String str) {
       char[] chars = str.toCharArray();
       Arrays.sort(chars);
       return new String(chars);
   }

}

运行示例,输出如下:

Oen
Tow
Teehr

类::静态方法

用于引用类上面的静态方法,下面实例将引用自定义 MyStr 类中的 sort 静态方法,如下:

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Demo06 {

   public static void main(String[] args) {
       List<String> list = Stream.of("One", "Two", "Three")
               .map(MyStr::sort) // 应用静态方法
               .collect(Collectors.toList());
       for(String str : list) {
           System.out.println(str);
       }
   }

}

class MyStr {

   // 静态方法,对字符串按字符排序
   public static String sort(String str) {
       char[] chars = str.toCharArray();
       Arrays.sort(chars);
       return new String(chars);
   }

}

运行示例,输出如下:

Oen
Tow
Teehr

类::实例方法

用于引用类上面的实例方法,下面实例将引用 String 类的 toLowerCase 方法,如下:

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Demo06 {

   public static void main(String[] args) {
       List<String> list = Stream.of("One", "Two", "Three")
               .map(String::toLowerCase) // 引用类的实例方法
               .collect(Collectors.toList());
       for(String str : list) {
           System.out.println(str);
       }
   }

}

运行示例,输出如下:

one
two
three

this::实例方法

下面演示通过 this 引用本类上的 convert 实例方法,如下:

package com.hxstrive.jdk8.method_ref;

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
* “this::实例方法” 使用方式
* @author hxstrive.com
*/
public class MethodRef04 {

   public static void main(String[] args) {
       new MethodRef04();
   }

   public MethodRef04() {
       List<String> list = Stream.of("Hello", "World")
               // 使用 this 的方式引用当前实例的 convert 方法
               .map(this::convert)
               .collect(Collectors.toList());
       for(String str : list) {
           System.out.println(str);
       }
   }

   private String convert(String str) {
       return "[" + str.toUpperCase() + "]";
   }

}

运行示例,输出如下:

[HELLO]
[WORLD]

super::实例方法

下面演示通过 super 引用父类上的 convert 实例方法,如下:

package com.hxstrive.jdk8.method_ref;

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
* “super::实例方法” 使用方式
* @author hxstrive.com
*/
public class MethodRef05 extends MethodRef05Super {

   public static void main(String[] args) {
       new MethodRef05();
   }

   public MethodRef05() {
       List<String> list = Stream.of("Hello", "World")
               // 使用 super 的方式引用父类的 convert 方法
               .map(super::convert)
               .collect(Collectors.toList());
       for(String str : list) {
           System.out.println(str);
       }
   }



}

class MethodRef05Super {

   public String convert(String str) {
       return "[" + str.toUpperCase() + "]";
   }

}

运行示例,输出如下:

[HELLO]
[WORLD]
说说我的看法
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
公众号