在上一篇文章中我们介绍了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. npm install @wepy/cli -g 出错

    npm install @wepy/cli -g 出错:npm ERR! Unexpected end of JSON input while parsing near '...1.0.0" ...

  2. Visual Studio编译Core程序部署到linux

    一.背景 随着微软拥抱开源,推出Net Core框架,目前已经支持跨平台,能部署到Linux.MacOS.Windows等系统上. 下面我们就来分享一下Visual Studio编译好的代码部署到Li ...

  3. VMware Workstation Pro15安装路径、修复等问题

    我的VMware Worstation 昨晚报错,无法打开虚拟机,VMware Authorization Services 也无法启动,于是卸载重装,结果仍然无法启动VMware Authoriza ...

  4. css实例——“旋转”太极八卦图

    话不多说,直接上代码: HTML代码部分: <!DOCTYPE html> <html> <head> <meta charset="utf-8&q ...

  5. 洛谷 P4093 [HEOI2016/TJOI2016]序列 CDQ分治优化DP

    洛谷 P4093 [HEOI2016/TJOI2016]序列 CDQ分治优化DP 题目描述 佳媛姐姐过生日的时候,她的小伙伴从某宝上买了一个有趣的玩具送给他. 玩具上有一个数列,数列中某些项的值可能会 ...

  6. 跟着尚硅谷系统学习Docker-【day01】

    day01-20200710   p1.基础知识   鲸鱼背上有一些集装箱   学习docker得基础知识   1.强制:熟悉Linux命令和相关背景知识 2.建议有maven和git的相关知识   ...

  7. 深入理解 JVM 的内存区域

    深入理解运行时数据区 代码示例: 1. JVM 向操作系统申请内存: JVM 第一步就是通过配置参数或者默认配置参数向操作系统申请内存空间,根据内存大小找到具体的内存分配表,然后把内存段的起始地址和终 ...

  8. SpringBoot2 引入 Aop

    一步小心就掉进坑里面了:SpringBoot2 引入 Aop 不生效 SpringBoot2.1.3版本 首先,引入依赖 <!--面向切面--> <dependency> &l ...

  9. 在Oracle Sql Developer/Sql Plus中查看oracle版本

    输入select * from v$version; 执行即可. 此法在Sql plus中执行效果: SQL> select * from v$version; BANNER --------- ...

  10. VS调试出现解决 尝试加载 Oracle 客户端库时引发 BadImageFormatException。如果在安装 32 位 Oracle 客户端组件的情况下以 64 位模式运行,将出现此问题