java8的方法引用详解(让你的代码看起来高大上)

2023-11-07 10:08

本文主要是介绍java8的方法引用详解(让你的代码看起来高大上),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在上一篇文章中曾经介绍到了java8中的Lambda表达式,这篇文章是基于Lambda表达式来叙述的。主要讲解方法引用。在此之前还希望你能够了解一下函数式接口的使用。

一、什么是方法引用

在Lambda表达式中,将其划分了几块。这一行就是lambda表达式。() -> System.out.println(“使用Lambda表达式”);下面我们对lambda的格式进行一个介绍:

(1)左边括号:lambda的形参列表,就好比是我们定义一个接口,里面有一个抽象方法,这个抽象方法的形参列表。

(2)箭头:lambda的操作符,所以你看见这个箭头心中知道这是一个lambda表达式就可以了。

(3)右边lambda体:就好比是我们实现了接口中的抽象方法。

在最后一块中,有时候,lambda体可能仅仅调用一个已存在的方法,而不做任何其它事,对于这种情况,通过一个方法名字来引用这个已存在的方法会更加清晰。

所以我们来总结:方法引用是一个更加紧凑,易读的 Lambda 表达式,注意方法引用是一个 Lambda 表达式,其中方法引用的操作符是双冒号 “::”。

二、举例演示

1、我们首先定义一个User类

public class Person {String name;LocalDate birthday;public Person(String name, LocalDate birthday) {this.name = name;this.birthday = birthday;}public LocalDate getBirthday() {return birthday;}public static int compareByAge(Person a, Person b) {return a.birthday.compareTo(b.birthday);}@Overridepublic String toString() {return this.name;}
}

现在有一个功能,那就是需要按照年龄,对Person进行排序。

2、Lambda表达式写法

public class RefSort {public static void main(String[] args) {Person[] pArr = new Person[]{new Person("1", LocalDate.of(2019, 12, 1)),new Person("2", LocalDate.of(2019, 12, 2)),new Person("3", LocalDate.of(2019, 12, 3)),new Person("4", LocalDate.of(2019, 12, 4))};Arrays.sort(pArr, (Person a, Person b) -> {return a.getBirthday().compareTo(b.getBirthday());});System.out.println(Arrays.asList(pArr));}
}

我们使用lambda表达式可以直接进行比较。现在我们使用方法引用。

public class RefSort { public static void main(String[] args) {Person[] pArr = new Person[]{ new Person("1", LocalDate.of(2019, 12, 1)),new Person("2", LocalDate.of(2019, 12, 2)),new Person("3", LocalDate.of(2019, 12, 3)),new Person("4", LocalDate.of(2019, 12, 4))};Arrays.sort(pArr, Person::compareByAge);System.out.println(Arrays.asList(pArr));}
}

这下子代码是不是更加的简洁了。我们相当于把lambda表达式进行了改变。下面我们就来好好地讲解一下方法引用是如何使用的。

三、方法引用分类

先来说一下方法引用使用到的操作符“::”,这个操作符把方法引用分成两边,左边是类名或者某个对象的引用,右边是方法名。引用方法有下面几种方式:

(1)对象引用::实例方法名

(2)类名::静态方法名

(3)类名::实例方法名

(4)类名::new

(5)类型[]::new

我们对这5种方式分别来叙述。

1、对象引用::实例方法名

public class PersonCompare {public int compareByName(Person a, Person b) {return a.getName().compareTo(b.getName());}public int compareByAge(Person a, Person b) {return a.getBirthday().compareTo(b.getBirthday());}@Testpublic void test(){Person[] pArr = new Person[]{new Person("1", LocalDate.of(2019, 12, 1)),new Person("2", LocalDate.of(2019, 12, 2)),new Person("3", LocalDate.of(2019, 12, 3)),new Person("4", LocalDate.of(2019, 12, 4))};PersonCompare personCompare = new PersonCompare();Arrays.sort(pArr, personCompare::compareByName);}
}

我们创建了一个PersonCompare对象,调用了其内部的compareByName实例方法。

2、类名::静态方法名

举几个例子:

String::valueOf,等价于 Lambda:s -> String.valueOf(s)

Math::pow 等价于lambda表达式 (x, y) -> Math.pow(x, y);

Person::compareByAge 就是一个静态方法引用,也是前面我们举得例子。

Function<Long, Long> f = Math::abs;
Long result = f.apply(-3L);123

Math是一个类而abs为该类的静态方法。Function中的唯一抽象方法apply方法参数列表与abs方法的参数列表相同,都是接收一个Long类型参数。

3、类名::实例方法名

若Lambda表达式的参数列表的第一个参数,是实例方法的调用者,第二个参数(或无参)是实例方法的参数时,就可以使用这种方法:

BiPredicate<String, String> b = String::equals;
b.test("abc", "abcd");

String是一个类而equals为该类的定义的实例方法。BiPredicate中的唯一抽象方法test方法参数列表与equals方法的参数列表相同,都是接收两个String类型参数。

4、类名::new

在引用构造器的时候,构造器参数列表要与接口中抽象方法的参数列表一致。对应的 Lambda:() -> new String()。

class PersonFactory {private Supplier<Person> supplier;public PersonFactory(Supplier<Person> supplier) {this.supplier = supplier;}public Person getPerson() {return supplier.get();}
}
PersonFactory factory = new PersonFactory(Person::new);
Person p1 = factory.getPerson();

上面这段代码的功能就是使用PersonFactory工厂,然后使用Person::new创建一个Person实例。

5、类型[]::new

引用数组和引用构造器很像,格式为 类型[]::new,等价于 lambda 表达式 x -> new int[x]。其中类型可以为基本类型也可以是类。

Function<Integer, int[]> fun = int[]::new;
int[] arr = fun.apply(10);
Function<Integer, Integer[]> fun2 = Integer[]::new;
Integer[] arr2 = fun2.apply(10);

OK。方法引用就是这么简单。

喜欢的可以关注我的公众号:java的架构师技术栈,获取更多文章和教程资源

这篇关于java8的方法引用详解(让你的代码看起来高大上)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/362909

相关文章

MySQL 中的 JSON 查询案例详解

《MySQL中的JSON查询案例详解》:本文主要介绍MySQL的JSON查询的相关知识,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录mysql 的 jsON 路径格式基本结构路径组件详解特殊语法元素实际示例简单路径复杂路径简写操作符注意MySQL 的 J

Java学习手册之Filter和Listener使用方法

《Java学习手册之Filter和Listener使用方法》:本文主要介绍Java学习手册之Filter和Listener使用方法的相关资料,Filter是一种拦截器,可以在请求到达Servl... 目录一、Filter(过滤器)1. Filter 的工作原理2. Filter 的配置与使用二、Listen

Pandas统计每行数据中的空值的方法示例

《Pandas统计每行数据中的空值的方法示例》处理缺失数据(NaN值)是一个非常常见的问题,本文主要介绍了Pandas统计每行数据中的空值的方法示例,具有一定的参考价值,感兴趣的可以了解一下... 目录什么是空值?为什么要统计空值?准备工作创建示例数据统计每行空值数量进一步分析www.chinasem.cn处

Spring Boot中JSON数值溢出问题从报错到优雅解决办法

《SpringBoot中JSON数值溢出问题从报错到优雅解决办法》:本文主要介绍SpringBoot中JSON数值溢出问题从报错到优雅的解决办法,通过修改字段类型为Long、添加全局异常处理和... 目录一、问题背景:为什么我的接口突然报错了?二、为什么会发生这个错误?1. Java 数据类型的“容量”限制

Java对象转换的实现方式汇总

《Java对象转换的实现方式汇总》:本文主要介绍Java对象转换的多种实现方式,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录Java对象转换的多种实现方式1. 手动映射(Manual Mapping)2. Builder模式3. 工具类辅助映

SpringBoot请求参数接收控制指南分享

《SpringBoot请求参数接收控制指南分享》:本文主要介绍SpringBoot请求参数接收控制指南,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Spring Boot 请求参数接收控制指南1. 概述2. 有注解时参数接收方式对比3. 无注解时接收参数默认位置

利用Python调试串口的示例代码

《利用Python调试串口的示例代码》在嵌入式开发、物联网设备调试过程中,串口通信是最基础的调试手段本文将带你用Python+ttkbootstrap打造一款高颜值、多功能的串口调试助手,需要的可以了... 目录概述:为什么需要专业的串口调试工具项目架构设计1.1 技术栈选型1.2 关键类说明1.3 线程模

SpringBoot基于配置实现短信服务策略的动态切换

《SpringBoot基于配置实现短信服务策略的动态切换》这篇文章主要为大家详细介绍了SpringBoot在接入多个短信服务商(如阿里云、腾讯云、华为云)后,如何根据配置或环境切换使用不同的服务商,需... 目录目标功能示例配置(application.yml)配置类绑定短信发送策略接口示例:阿里云 & 腾

Python ZIP文件操作技巧详解

《PythonZIP文件操作技巧详解》在数据处理和系统开发中,ZIP文件操作是开发者必须掌握的核心技能,Python标准库提供的zipfile模块以简洁的API和跨平台特性,成为处理ZIP文件的首选... 目录一、ZIP文件操作基础三板斧1.1 创建压缩包1.2 解压操作1.3 文件遍历与信息获取二、进阶技

SpringBoot项目中报错The field screenShot exceeds its maximum permitted size of 1048576 bytes.的问题及解决

《SpringBoot项目中报错ThefieldscreenShotexceedsitsmaximumpermittedsizeof1048576bytes.的问题及解决》这篇文章... 目录项目场景问题描述原因分析解决方案总结项目场景javascript提示:项目相关背景:项目场景:基于Spring