java8简化的可变参数调用,Java8新特性--方法引用
一.什么是方法引用?
谈到方法引用,就必须提到Lambda,因为方法引用是用在Lambda表达式的,方法引用是一种更简洁易懂的Lambda表达式,和Lambda表达式一样,也是一种语法糖。
当我们需要使用Lambda表达式来实现一个函数式接口的抽象方法时,已经有存在的类实现了我们需要的功能方法,这时我们完全没必要再造一个实现方法,可以直接用Lambda表达式调用这个方法来实现,虽然这样子实现可以,但是很冗余,此时使用方法引用就很简洁清晰,可读性更高。
方法引用的运算符为::。
下面用一个例子解释下上面所说的:(方法引用的使用下面会再讲)
// 之前介绍的函数式接口中有个消费型接口Consumer,抽象方法accept接收一个参数,没有返回值
public static void main(String[] args) {
Consumer consumer = (s) -> System.out.println(s);
consumer.accept("Hello Java");
}
上面Consumer接口中的抽象方法accept实现的是打印传入的字符串,Lambda表达式中调用的是System.out.println,是System.out已经实现了的,所以在Lambda表达式中我就没有自己实现一个打印的方法,而是直接调用了已存在的方法,这里就可以使用方法引用来简化代码了,简化后如下所示:
public static void main(String[] args) {
Consumer consumer = System.out:println;
consumer.accept("Hello Java");
}
重点:看了上面所说所演示,那为啥这样子的就可以用方法引用来简化呢?
System.out是存在的对象
println是已存在的方法
函数接口的方法accept的参数类型是String,并且无返回值,与方法引用的println参数类型一致。
所以,要能使用方法引用,必须满足:方法引用的对象或类是存在的或已知的,方法也是存在的,还需要方法参数列表保持一致。
二.方法引用的分类
总共有三种引用,引用方法,引用构造器,引用数组。有如下几种分类
1. 通过对象引用成员方法
举例:
public static void main(String[] args) {
// 使用Lambda
Consumer consumer = (s) -> System.out.println(s);
// 使用方法引用
Consumer consumer1 = System.out::println;
consumer.accept("hello");
consumer1.accept("hello");
}
解释:System.out是PrintStream类型的对象引用,println是一个成员方法,而Consumer是一个函数式接口,内部的抽象方法为accept,参数列表与println参数列呗一致,都是接收一个String类型参数,所以可以使用方法引用,这种就是对象引用成员方法。
2. 通过类名引用静态方法
举例:
public static void main(String[] args) {
// 使用Lambda
Function func = (i) -> Math.abs(i);
Integer i = func.apply(-10);
System.out.println(i);
// 使用方法引用
Function func1 = Math::abs;
Integer i1 = func1.apply(-10);
System.out.println(i1);
}
解释:Math是一个类,而abs是Math类的静态方法;Function接口中抽象方法apply参数列表与abs方法的参数列表是一致的,因此可以使用方法引用,这种就是通过类名引用静态方法。
3.类的构造器引用
由于构造器名字和类名一样,并不是固定的,所以构造器的引用使用格式:类名::new
举例:
class Person {
private String name;
public Person(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
}
interface PersonBuilder {
public abstract Person buildPerson(String name);
}
public class MethodReferenece {
public static void main(String[] args) {
// Lambda方式
PersonBuilder pb = (name) -> new Person(name);
System.out.println(pb.buildPerson("zhangsan").getName());
// 方法引用
PersonBuilder pb1 = Person::new;
System.out.println(pb1.buildPerson("lisi").getName());
}
}
解释:PersonBuilder接口的抽象方法是buildPerson是为了返回一个Person对象,那必须要new一个对象返回,new一个对象实质就是调用了构造方法,而且类Person存在,带参构造方法也存在,并且参数与函数式接口的抽象方法一样,都是String,所以可以使用方法引用,用类的构造器引用。
4. 数组的构造器引用
数组也是Object的子类对象,所以同样是具有构造器的,实质也是构造器的引用,但是语法格式有些不同,数组的构造器引用格式为:类型[]::new,其中这个类型可以是基本类型也可以是类。
举例:
interface ArrayBuilder {
public abstract int[] buildArray(int length);
}
public class MethodReferenece {
public static void main(String[] args) {
// Lambda方式
ArrayBuilder ab = (len) -> new int[len];
int[] array = ab.buildArray(5);
for (int i = 0; i < array.length; i++) {
array[i] = i;
}
for (int i: array) {
System.out.println(i);
}
// 方法引用
ArrayBuilder ab1 = int[]::new;
int[] array1 = ab1.buildArray(5);
for (int i = 0; i < array1.length; i++) {
array1[i] = i * 2;
}
for (int i: array1) {
System.out.println(i);
}
}
}
解释:这里演示了使用int[]数组的构造器引用,这里使用int[]::new时候,根据函数式接口ArrayBuilder的抽象函数buildArray的参数列表是一个整形,会自动调用的是new一个数组的时候带一个整形参数的构造方法,所以参数一致,也是可以使用方法引用的,这种就是数组的构造器引用。
三.总结
并不是所有的Lambda表达式都可以使用方法引用的,复杂的Lambda表达式还是得用Lambda表达式编写。
但使用方法引用会比较清晰简洁,能使用的地方还是推荐使用。
java8简化的可变参数调用,Java8新特性--方法引用相关推荐
- java 1.7 可变参数,JDK1.7新特性(2):异常和可变长参数处理
异常 jdk1.7对try--catch--finally的异常处理模式进行了增强,下面我们依次来看增强的方面. 1. 为了防止异常覆盖,给Throwable类增加了addSuppressed方法,可 ...
- 面试官问我Java8~14的有哪些重要的新特性,我哭了~~~
大家好,我是Guide哥!这篇文章来自读者的投稿,经过了两次较大的改动,两周的完善终于完成.Java 8新特性见这里:Java8新特性最佳指南 . Guide 哥:别人家的特性都用了几年了,我 Jav ...
- python可变参数调用函数问题
一直使用python实现一些想法,最近在使用python的过程中出现这样一个需求,定义了一个函数,第一个是普通参数,第二个是默认参数,后面还有可变参数,在最初学习python的时候,都知道非关键字可变 ...
- java5新特性静态引用、foreach、自动装箱和泛型枚举以及可变参数的总结
静态引用 导入(import)表示去找哪一个类,去哪一个包下去找哪些被使用到的类. 在java中有一个语言核心包:java.lang. 使用java.lang包中的API,不需要引用,直接能找到,但是 ...
- php函数可变参数列表,PHP函数可变参数列表的具体实现方法介绍
也许对于PHP初级程序员来说,对于PHP函数并不能完全熟练的掌握.我们今天为大家介绍的PHP函数可变参数列表的实现方法主要是利用func_get_args(). func_num_args().fun ...
- Java笔记_16(不可变集合、Stream流、方法引用)
Java笔记_16 一.创建不可变集合 1.1.创建不可变集合的应用场景 1.2.创建不可变集合的书写格式 二.Stream流 2.1.体验Stream流 2.2.Stream流的思想和获取Strea ...
- spring security 方法安全表达式 使用参数 调用bean 自定义校验方法
版本 spring security 5.6.6 使用参数 在鉴权表达式中通过**#参数名**格式引用参数值 可以通过*@P*注解给参数添加别名 import org.springframework. ...
- ES6新特性_ES6生成器函数声明与调用---JavaScript_ECMAScript_ES6-ES11新特性工作笔记020
然后我们再来看这个 生成器函数的声明调用 生成器函数就是在函数,前面加个*,表示这个是个生成器函数. 然后我们写个iterator=gen(); 调用一下这个函数,看看这个函数中有个next方法 所以 ...
- jdk1.5-1.7新特性详细介绍
jdk1.5新特性 1.泛型 2.foreach 3.自动拆箱装箱 4.枚举 5.静态导入(Static import) 6.元数据(Metadata) 7.线程池 8.Java Generics ...
最新文章
- 21.5. 流量控制
- C和指针之函数之实现阶乘和斐波那契数(递归和非递归)
- HDOJ 1012-1020
- .Net开源的跨平台爬虫框架 DotnetSpider
- iPhone 12的4G/5G信号又翻车了:不少用户吐槽无网络服务
- 关于a元素href的注意点
- 《Java核心技术 卷12》读书笔记
- 随机过采样与随机欠采样 代码
- 【java模板引擎】-beetl
- Golang AES加密解密
- Bootstrap系列之下拉菜单(Dropdowns)
- Android 腾讯 云通信 用户头像更新
- 【工具】D2RQ安装和配置
- x64dbg 自动化控制插件
- Java代码审计学习笔记
- freeswitch语音识别一系列干货
- centos怎么用命令关机_CentOS关机命令
- etcd入门系列三:身份验证访问控制
- SLAM流程之视觉前端
- 数学:逻辑:符号逻辑(翻译)
热门文章
- 实习生使用微软雅黑致公司被起诉索赔千万?方正回应...
- 后置三摄!郭明錤再曝新一代iPhone:屏幕变化不大
- 在网页中通过百度地图查看某地的经纬度
- CentOS 7 巨大变动之 systemd 取代 SysV的Init
- 晨哥真有料丨自信一点!恋爱做自己,不要自卑,不要迎合!
- 自由读写配置文件的艺术[java c++ node](二)
- 在代码中实用协程(二)
- “命令终端”的实现4-优化之解耦
- 遇到一个Linux文件系统因bios时间错误变成只读的问题
- 由“标准C”“纯C”引发的思考