在上一篇文章中我们介绍了JDK1.8的新特性有以下几项。

1.Lambda表达式

2.方法引用

3.函数式接口

4.默认方法

5.Stream

6.Optional类

7.Nashorm javascript引擎

8.新的日期时间API

9.Base64

并且学习了JDK1.8最重要的特性--Lambda表达式这一篇学习方法引用。

首先介绍方法引用是啥?

方法引用单从“引用”二字不难理解,我们经常拿毛主席的”不管黑猫白猫能抓住老鼠的猫就是好猫“这句话来说事情,这里就是引用了毛主席的话。那么方法引用就是拿过其他地方已经存在的方法,我们拿过来使用,在这里可以理解成Lambda表达式的一种特殊用法。只是我们得按照一定的规则来用。也就是我们接下来要重点要学习的内容:方法引用的方式

接下来先列出方法引用的方式。

总体来说方法引用有三种方式,分别如下。

  1.普通方法引用
1.1 实例方法引用(通过实例对象)
对象::实例方法名;
1.2 静态方法引用
类名::静态方法名;
1.3 实例方法引用(通过类名)
类名::实例方法名;
注:上面两种实例方法引用的不同之处,通过下面代码详细说明。
  2.构造器引用
类名::new;
  3.数组引用
类型::new;

下面重点通过实例来学习上面的集中形式。
1.1 实例方法引用(通过实例对象)
下面通过最简单的打印输出语句来理解实例方法引用。
 1 public class MethodReferenceTest {
2
3 /**
4 * 为了更容易理解方法引用
5 * 我通过正常的Lambda表达式和方法引用两种方式来实现代码部分
6 */
7 //*****************************
8 // 方法引用的形式一 对象::实例方法名
9 //*****************************
10 @Test
11 public void test1(){
12 //Lambda表达式
13 PrintStream ps1 = System.out;
14 Consumer con1 = x -> ps1.println(x);
15 con1.accept("Hello Lambda表达式!");
16
17 //方法引用
18 PrintStream ps2 = System.out;
19 Consumer con2 = ps2::println;
20 con2.accept("Hello 方法引用!");
21 }
22
23 }

执行结果

...
com.dream.test.JDK8speciality.MethodReferenceTest,test1
Hello Lambda表达式!
Hello 方法引用! Process finished with exit code 0

通过上面实例14行和19行的对比可以看出,使用方法引用的方式比直接Lambda表达式更简洁,再次也可以看做方法引用是Lambda表达式的一种特殊写法,学习了Lambda表达式,方法引用的写法也就不难理解了。

注:Consumer是JDK1.8的java.util.function包下提供的一个函数式接口,accept方法接收一个泛型<T>类型,返回值为void的抽象方法。具体实现是Lambda表达式的部分去实现的,也就是 x -> ps1.println(x); 和 ps2::println; 关于JDK1.8提供的函数式接口会在后面函数式接口章节进行学习。

1.2 静态方法引用
下面通过比较两个整数的大小来理解静态方法的引用。
 1 public class MethodReferenceTest {
2
3 //*****************************
4 // 方法引用的形式二 类名::静态方法名
5 //*****************************
6 @Test
7 public void test2(){
8 //Lambda表达式
9 //x > y:返回1;
10 //x = y:返回0;
11 //x < y:返回-1;
12 Comparator<Integer> com1 = (x,y)->Integer.compare(x,y);
13 Integer i1=com1.compare(2,1);
14 System.out.println("Lambda表达式结果:" + i1);
15
16 //方法引用
17 Comparator<Integer> com2 = Integer::compare;
18 Integer i2=com2.compare(2,1);
19 System.out.println("方法引用结果:" + i2);
20 }
21
22 }

执行结果

com.dream.test.JDK8speciality.MethodReferenceTest,test2
Lambda表达式结果:1
方法引用结果:1 Process finished with exit code 0

正常通过Lam表达式我们 (x,y)->Integer.compare(x,y);这样写,由于Integer类下有静态方法已经实现了两个整数的比较,所有我们通过静态方法引用的方式直接引用就好了。由此变成了Integer::compare;

1.3 实例方法引用(通过类名)
通过比较两个字符串的内容来说明。
 1 public class MethodReferenceTest {
2
3 //*****************************
4 // 方法引用的形式三 类名::实例方法
5 //*****************************
6 @Test
7 public void test3(){
8 //比较两个字符串的内容
9 //Lambda表达式
10 BiPredicate<String,String> bp1 = (s1,s2) -> s1.equals(s2);
11 boolean b1 = bp1.test("abc","abc");
12 System.out.println("Lambda结果:" + b1);
13
14 //方法引用
15 BiPredicate<String,String> bp2 = String::equals;
16 boolean b2 = bp2.test("abc","abc");
17 System.out.println("方法结果:" + b2);
18 }
19
20 }

执行结果

...
com.dream.test.JDK8speciality.MethodReferenceTest,test3
Lambda结果:true
方法结果:true Process finished with exit code 0

通过对象的方式引用和通过类名的方式引用不同之处是:当函数式参数列表的第一个参数是方法的调用者,而且第二个参数是被调用方法的参数的时候,我们就需要用【类名::方法名】的方式来书写代码。

这里的BiPredicate也是JDK1.8的java.util.function包下的函数是接口,关于函数式接口会在后面函数式接口章节进行学习,在这里知道它是函数接口接口即可。

2.构造器引用

由于构造器是创建对象的时候使用的所以这里也是要用new关键字的。也就是【类名::new】的形式。

 1 public class MethodReferenceTest {
2 //*****************************
3 // 构造器引用 类名::实例方法
4 //*****************************
5 @Test
6 public void test4(){
7 //通过无参数的构造器创建对象
8 System.out.println("无参构造器");
9 //Lambda表达式
10 System.out.println("Lambda表达式:");
11 Supplier<User> su1 =() -> new User();//Lambda表达式没有参数的时候圆括号不可省略
12 User user1 = su1.get();
13 System.out.println("userName:" + user1.getUserName() + " pwd:" + user1.getPwd());
14
15 //构造器引用
16 System.out.println("构造器引用:");
17 Supplier<User> su2 = User::new;
18 User user2 = su2.get();
19 System.out.println("userName:" + user2.getUserName() + " pwd:" + user2.getPwd());
20
21 //通过有参数的构造器创建对象
22 System.out.println("有参数构造器");
23 //Lambda表达式
24 System.out.println("Lambda表达式:");
25 BiFunction<String,String,User> bf1 = (userName,pwd) -> new User(userName,pwd);
26 User user3 = bf1.apply("12345@163.com","987654321");
27 System.out.println("userName:" + user3.getUserName() + " pwd:" + user3.getPwd());
28
29 //构造器引用
30 System.out.println("构造器引用:");
31 BiFunction<String,String,User> bf2 = User::new;
32 User user4 = bf2.apply("12345@163.com","987654321");
33 System.out.println("userName:" + user4.getUserName() + " pwd:" + user4.getPwd());
34
35 /**
36 * 通过对以上有参数,无参数的构造器引用的实例可以看出:
37 * 无论构造器参数有几个,引用部分的代码都是ClassName::new,不同的是函数式接口。
38 */
39 }
40
41 }

执行结果

...
com.dream.test.JDK8speciality.MethodReferenceTest,test4
无参构造器
Lambda表达式:
userName:null pwd:null
构造器引用:
userName:null pwd:null
有参数构造器
Lambda表达式:
userName:12345@163.com pwd:987654321
构造器引用:
userName:12345@163.com pwd:987654321 Process finished with exit code 0

有了前面几个方法引用的了解这里也就不难理解,只要记住构造方法引用的形式即可。需要注意的是:当Lambda表达式的没有参数的时候必须写上【() -> 】不能省略,否则报错。

还有一个需要注意的点就是,无论构造器有几个参数,构造器引用的形式都是【类名::构造器名】。变化的使用的函数式接口不同而已。关于函数式接口详细会在后面函数式接口章节进行学习。

3.数组引用

数组引用的形式和构造器引用的形式类似只是变成了【类名[]::构造器名】而已。也不用做过多解释。直接看例子即可。

 1 public class MethodReferenceTest {
2
3 //*****************************
4 // 数组引用 类型::new
5 //*****************************
6 @Test
7 public void test5(){
8 //Lambda表达式
9 Function<Integer,Integer[]> f1 =i -> new Integer[i];
10 Integer[] iArray1 = f1.apply(10);
11 System.out.println("Lambda表达式:Array长度为" + iArray1.length);
12
13 //数组引用
14 Function<Integer,Integer[]> f2 =Integer[]::new;
15 Integer[] iArray2 = f2.apply(10);
16 System.out.println("数组引用:Array长度为" + iArray2.length);
17 }
18
19 }

执行结果

...
com.dream.test.JDK8speciality.MethodReferenceTest,test5
Lambda表达式:Array长度为10
数组引用:Array长度为10 Process finished with exit code 0

这里使用了Function函数式接口,也会在接下来的文章中解释。

以上就是我对于方法引用的理解,如果有理解错误或者写的不好的地方还请各位大神不吝赐教呀。欢迎指正。

 

上一篇文章

JDK1.8新特性之(一)--Lambda表达式

JDK1.8新特性之(二)--方法引用的更多相关文章

  1. JAVA 8 主要新特性 ----------------(五)Lambda方法引用与构造器引用

    一.Lambda方法引用 当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用!(实现抽象方法的参数列表,必须与方法引用方法的参数列表保持一致!) 方法引用: 使用操作符 “::” 将 ...

  2. JDK1.8新特性(二):Collectors收集器类

    一. 什么是Collectors? Java 8 API添加了一个新的抽象称为流Stream,我们借助Stream API可以很方便的操作流对象. Stream中有两个方法collect和collec ...

  3. JDK1.8新特性(一) ----Lambda表达式、Stream API、函数式接口、方法引用

    jdk1.8新特性知识点: Lambda表达式 Stream API 函数式接口 方法引用和构造器调用 接口中的默认方法和静态方法 新时间日期API default   Lambda表达式     L ...

  4. Java8新特性之二:方法引用

    上一节介绍了Java8新特性中的Lambda表达式,本小节继续讲解Java8的新特性之二:方法引用.方法引用其实也离不开Lambda表达式. 1.方法引用的使用场景 我们用Lambda表达式来实现匿名 ...

  5. jdk1.8新特性之方法引用

    方法引用其实就是方法调用,符号是两个冒号::来表示,左边是对象或类,右边是方法.它其实就是lambda表达式的进一步简化.如果不使用lambda表达式,那么也就没必要用方法引用了.啥是lambda,参 ...

  6. JDK1.8新特性(一): 接口的默认方法default

    前言 今天在学习mysql分区优化时,发现一个博客专家大神,对其发布的文章简单学习一下: 一:简介 我们通常所说的接口的作用是用于定义一套标准.约束.规范等,接口中的方法只声明方法的签名,不提供相应的 ...

  7. JavaSE----API之集合(Collection、List及其子类、Set及其子类、JDK1.5新特性)

    5.集合类 集合类的由来: 对象用于封装特有数据,对象多了须要存储:假设对象的个数不确定.就使用集合容器进行存储. 集合容器由于内部的数据结构不同,有多种详细容器.不断的向上抽取,就形成了集合框架. ...

  8. JDK1.8新特性之(三)--函数式接口

    在上一篇文章中我们介绍了JDK1.8的新特性有以下几项. 1.Lambda表达式 2.方法引用 3.函数式接口 4.默认方法 5.Stream 6.Optional类 7.Nashorm javasc ...

  9. JDK1.8新特性之(一)--Lambda表达式

    近期由于新冠疫情的原因,不能出去游玩,只能在家呆着.于是闲来无事,开始阅读JDK1.8的源代码.在开始之前也查询了以下JDK1.8的新特性,有针对性的开始了这段旅程. 只看不操作,也是不能心领神会的. ...

随机推荐

  1. C++入门记-构造函数和析构函数

    前文回顾 本文档环境基于Vscode + GCC + CodeRunner 关于C++的环境搭建请参考下面链接: C++入门记-大纲 由于本人具有C#开发经验,部分相同的知识就不再赘述了.只列一下需要 ...

  2. Spark保存的时候怎么去掉多余的引号转义

    今天用SparkSQL保存一份json数据的时候,引号被转义了,并用括号包起来了,导致下游新来的小伙伴无法处理这份数据. 保存后的数据长这样(用\t分割): data "{\"ke ...

  3. 【HttpRunner v3.x】笔记 —— 开篇

    最近在社群聊天里,发现了一款适用于http协议的接口框架--HttpRunner.在对其有个大致了解后,我觉得这款框架优点多多,整合了接口测试中所配套用到的多种框架.通过优秀的封装,将case整合到一 ...

  4. python学习第八天

    解析库之bs4的基本使用方法 ''' pip install beautifulsoup4#安装bs4 pip install lxml#安装lxml ''' html_doc = "&qu ...

  5. D - 英文题 (多组背包)

    The cows are going to space! They plan to achieve orbit by building a sort of space elevator: a gian ...

  6. 08_线程间通信 ITC

    1.线程间的通信方式 1.共享全局变量 2.线程队列(queue) 3.信号量(Semaphore) 2.共享全局变量进行通信 from threading import Thread import ...

  7. boot 项目启动报Cannot datermine embedded database driver class for database type NONE

    部署boot项目时报Cannot datermine embedded database driver class for database type NONE数据库链接什么的也都没有问题,经过百度 ...

  8. CTF-WeChall-第四天上午

    2020.09.12 08:24 哈哈,go on!

  9. 一道JavaScript的二维数组求平均数的题

    JavaScript中只支持一维数组,但是可以在数组中嵌套数组来创建二维以至于多维的数组.今天下午在看书时候,发现一道感觉比较有意思的题,就是js中如何求二维数组的列之和和行之和,现在就给大家分享下, ...

  10. 最全总结 | 聊聊 Python 数据处理全家桶(Mysql 篇)

    1. 前言 在爬虫.自动化.数据分析.软件测试.Web 等日常操作中,除 JSON.YAML.XML 外,还有一些数据经常会用到,比如:Mysql.Sqlite.Redis.MongoDB.Memch ...