一.什么是方法引用?

​ 谈到方法引用,就必须提到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新特性--方法引用相关推荐

  1. java 1.7 可变参数,JDK1.7新特性(2):异常和可变长参数处理

    异常 jdk1.7对try--catch--finally的异常处理模式进行了增强,下面我们依次来看增强的方面. 1. 为了防止异常覆盖,给Throwable类增加了addSuppressed方法,可 ...

  2. 面试官问我Java8~14的有哪些重要的新特性,我哭了~~~

    大家好,我是Guide哥!这篇文章来自读者的投稿,经过了两次较大的改动,两周的完善终于完成.Java 8新特性见这里:Java8新特性最佳指南 . Guide 哥:别人家的特性都用了几年了,我 Jav ...

  3. python可变参数调用函数问题

    一直使用python实现一些想法,最近在使用python的过程中出现这样一个需求,定义了一个函数,第一个是普通参数,第二个是默认参数,后面还有可变参数,在最初学习python的时候,都知道非关键字可变 ...

  4. java5新特性静态引用、foreach、自动装箱和泛型枚举以及可变参数的总结

    静态引用 导入(import)表示去找哪一个类,去哪一个包下去找哪些被使用到的类. 在java中有一个语言核心包:java.lang. 使用java.lang包中的API,不需要引用,直接能找到,但是 ...

  5. php函数可变参数列表,PHP函数可变参数列表的具体实现方法介绍

    也许对于PHP初级程序员来说,对于PHP函数并不能完全熟练的掌握.我们今天为大家介绍的PHP函数可变参数列表的实现方法主要是利用func_get_args(). func_num_args().fun ...

  6. Java笔记_16(不可变集合、Stream流、方法引用)

    Java笔记_16 一.创建不可变集合 1.1.创建不可变集合的应用场景 1.2.创建不可变集合的书写格式 二.Stream流 2.1.体验Stream流 2.2.Stream流的思想和获取Strea ...

  7. spring security 方法安全表达式 使用参数 调用bean 自定义校验方法

    版本 spring security 5.6.6 使用参数 在鉴权表达式中通过**#参数名**格式引用参数值 可以通过*@P*注解给参数添加别名 import org.springframework. ...

  8. ES6新特性_ES6生成器函数声明与调用---JavaScript_ECMAScript_ES6-ES11新特性工作笔记020

    然后我们再来看这个 生成器函数的声明调用 生成器函数就是在函数,前面加个*,表示这个是个生成器函数. 然后我们写个iterator=gen(); 调用一下这个函数,看看这个函数中有个next方法 所以 ...

  9. jdk1.5-1.7新特性详细介绍

    jdk1.5新特性 1.泛型 2.foreach 3.自动拆箱装箱 4.枚举 5.静态导入(Static import) 6.元数据(Metadata) 7.线程池 8.Java Generics  ...

最新文章

  1. 21.5. 流量控制
  2. C和指针之函数之实现阶乘和斐波那契数(递归和非递归)
  3. HDOJ 1012-1020
  4. .Net开源的跨平台爬虫框架 DotnetSpider
  5. iPhone 12的4G/5G信号又翻车了:不少用户吐槽无网络服务
  6. 关于a元素href的注意点
  7. 《Java核心技术 卷12》读书笔记
  8. 随机过采样与随机欠采样 代码
  9. 【java模板引擎】-beetl
  10. Golang AES加密解密
  11. Bootstrap系列之下拉菜单(Dropdowns)
  12. Android 腾讯 云通信 用户头像更新
  13. 【工具】D2RQ安装和配置
  14. x64dbg 自动化控制插件
  15. Java代码审计学习笔记
  16. freeswitch语音识别一系列干货
  17. centos怎么用命令关机_CentOS关机命令
  18. etcd入门系列三:身份验证访问控制
  19. SLAM流程之视觉前端
  20. 数学:逻辑:符号逻辑(翻译)

热门文章

  1. 实习生使用微软雅黑致公司被起诉索赔千万?方正回应...
  2. 后置三摄!郭明錤再曝新一代iPhone:屏幕变化不大
  3. 在网页中通过百度地图查看某地的经纬度
  4. CentOS 7 巨大变动之 systemd 取代 SysV的Init
  5. 晨哥真有料丨自信一点!恋爱做自己,不要自卑,不要迎合!
  6. 自由读写配置文件的艺术[java c++ node](二)
  7. 在代码中实用协程(二)
  8. “命令终端”的实现4-优化之解耦
  9. 遇到一个Linux文件系统因bios时间错误变成只读的问题
  10. 由“标准C”“纯C”引发的思考