JDK1.8新特性之(二)--方法引用
在上一篇文章中我们介绍了JDK1.8的新特性有以下几项。
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新特性之(二)--方法引用的更多相关文章
- JAVA 8 主要新特性 ----------------(五)Lambda方法引用与构造器引用
一.Lambda方法引用 当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用!(实现抽象方法的参数列表,必须与方法引用方法的参数列表保持一致!) 方法引用: 使用操作符 “::” 将 ...
- JDK1.8新特性(二):Collectors收集器类
一. 什么是Collectors? Java 8 API添加了一个新的抽象称为流Stream,我们借助Stream API可以很方便的操作流对象. Stream中有两个方法collect和collec ...
- JDK1.8新特性(一) ----Lambda表达式、Stream API、函数式接口、方法引用
jdk1.8新特性知识点: Lambda表达式 Stream API 函数式接口 方法引用和构造器调用 接口中的默认方法和静态方法 新时间日期API default Lambda表达式 L ...
- Java8新特性之二:方法引用
上一节介绍了Java8新特性中的Lambda表达式,本小节继续讲解Java8的新特性之二:方法引用.方法引用其实也离不开Lambda表达式. 1.方法引用的使用场景 我们用Lambda表达式来实现匿名 ...
- jdk1.8新特性之方法引用
方法引用其实就是方法调用,符号是两个冒号::来表示,左边是对象或类,右边是方法.它其实就是lambda表达式的进一步简化.如果不使用lambda表达式,那么也就没必要用方法引用了.啥是lambda,参 ...
- JDK1.8新特性(一): 接口的默认方法default
前言 今天在学习mysql分区优化时,发现一个博客专家大神,对其发布的文章简单学习一下: 一:简介 我们通常所说的接口的作用是用于定义一套标准.约束.规范等,接口中的方法只声明方法的签名,不提供相应的 ...
- JavaSE----API之集合(Collection、List及其子类、Set及其子类、JDK1.5新特性)
5.集合类 集合类的由来: 对象用于封装特有数据,对象多了须要存储:假设对象的个数不确定.就使用集合容器进行存储. 集合容器由于内部的数据结构不同,有多种详细容器.不断的向上抽取,就形成了集合框架. ...
- JDK1.8新特性之(三)--函数式接口
在上一篇文章中我们介绍了JDK1.8的新特性有以下几项. 1.Lambda表达式 2.方法引用 3.函数式接口 4.默认方法 5.Stream 6.Optional类 7.Nashorm javasc ...
- JDK1.8新特性之(一)--Lambda表达式
近期由于新冠疫情的原因,不能出去游玩,只能在家呆着.于是闲来无事,开始阅读JDK1.8的源代码.在开始之前也查询了以下JDK1.8的新特性,有针对性的开始了这段旅程. 只看不操作,也是不能心领神会的. ...
随机推荐
- Asterisk-WebRTC客户端的部署
很久没有写博客了.最近完成asterisk 和 jssip的库集成,浏览器支持chrome/firefox.在集成的过程中遇到了一些问题,在这儿分享出来,免得大家走弯路. 在网上看一些帖子,环境都是 ...
- Apache Pulsar 社区周报:08-15 ~ 08-21
关于 Apache Pulsar Apache Pulsar 是 Apache 软件基金会顶级项目,是下一代云原生分布式消息流平台,集消息.存储.轻量化函数式计算为一体,采用计算与存储分离架构设计,支 ...
- 复杂一点的SQL语句:Oracle DDL和DML
DDL:对表或者表的属性进行了改变 create:创建表创建用户创建视图 创建表 create table student(id int,score int) ; student后面与括号之间可以有空 ...
- Canalv1.1.4版本搭建HA集群
前提 Canal上一个正式版是于2019-9-2发布的v1.1.4,笔者几个月前把这个版本的Canal推上了生产环境,部署了HA集群.过程中虽然遇到不少的坑,但是在不出问题的前提下,Canal的作用还 ...
- java安全编码指南之:声明和初始化
目录 简介 初始化顺序 循环初始化 不要使用java标准库中的类名作为自己的类名 不要在增强的for语句中修改变量值 简介 在java对象和字段的初始化过程中会遇到哪些安全性问题呢?一起来看看吧. 初 ...
- springboot2.x基础教程:Swagger详解给你的接口加上文档说明
相信无论是前端还是后端开发,都或多或少地被接口文档折磨过.前端经常抱怨后端给的接口文档与实际情况不一致.后端又觉得编写及维护接口文档会耗费不少精力,经常来不及更新.其实无论是前端调用后端,还是后端调用 ...
- MyBatis源码流程分析
mybatis核心流程三大阶段 Mybatis的初始化 建造者模式 建造者模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象.这种类型的设计模式属于创建型模式,它提 ...
- MySQL中存储json格式数据
1.1.1. JSON类型数据存储 新建表 create table json_user ( uid int auto_increment, data json, primary key(uid) ) ...
- asp.net中 使用Nginx 配置 IIS站点负载均衡
这是一偏初学者入门的内容,发现有问题的地方,欢迎留言,一起学习,一起进步 本文主要记录一下在Windows平台中,IIS站点如何使用Nginx 做一个简单的负载均衡 一. 准备工作: 官网下载安装包 ...
- 别再眼高手低了! 这些Linq方法都清楚地掌握了吗?
不要再眼高手低了,这些Enumerable之常见Linq扩展方法都清楚掌握了吗?其实这是对我自己来说的! 例如:一个人这个技术掌握了一点那个技术也懂一点,其他的好像也了解一些,感觉自己啥都会一点,又觉 ...