上一节介绍了Java8新特性中的Lambda表达式,本小节继续讲解Java8的新特性之二:方法引用。方法引用其实也离不开Lambda表达式。

1、方法引用的使用场景

  我们用Lambda表达式来实现匿名方法。但有些情况下,我们用Lambda表达式仅仅是调用一些已经存在的方法,除了调用动作外,没有其他任何多余的动作,在这种情况下,我们倾向于通过方法名来调用它,而Lambda表达式可以帮助我们实现这一要求,它使得Lambda在调用那些已经拥有方法名的方法的代码更简洁、更容易理解。方法引用可以理解为Lambda表达式的另外一种表现形式。

2、方法引用的分类

类型 语法 对应的Lambda表达式
静态方法引用 类名::staticMethod (args) -> 类名.staticMethod(args)
实例方法引用 inst::instMethod (args) -> inst.instMethod(args)
对象方法引用 类名::instMethod (inst,args) -> 类名.instMethod(args)
构建方法引用 类名::new (args) -> new 类名(args)

3、方法引用举例

3.1 静态方法引用

  有一个Person类,如下所示:

 @Data
public class Person { private String name; private Integer age; public static int compareByAge(Person a, Person b) {
return a.age.compareTo(b.age);
}
}

  现假设,一个部门有30人,把他们存放在一个数组中,并按年龄排序,通常我们可以自己写一个比较器,代码如下:

 Person[] rosterAsArray = new Person[30];
// 添加数组元素省略 class PersonAgeComparator implements Comparator<Person> {
public int compare(Person a, Person b) {
return a.getBirthday().compareTo(b.getBirthday());
}
} Arrays.sort(rosterAsArray, new PersonAgeComparator());

  Arrays.sort的声明为:public static <T> void sort(T[] a, Comparator<? super T> c),比较器参数Comparator为一个函数式接口,利用上一节Lambda表达式所学知识,可以改写为以下代码:

 Person[] rosterAsArray = new Person[30];
// 添加数组元素省略 Arrays.sort(rosterAsArray, (a,b) -> a.getAge().compareTo(b.getAge()));

  然而,你会发现,Perdon类中已经有了一个静态方法的比较器:compareByAge,因此,我们改用Person类已经提供的比较器:

 Person[] rosterAsArray = new Person[30];
// 添加数组元素省略 Arrays.sort(rosterAsArray, (a,b) -> Person.compareByAge(a,b));

  以上代码,因为Lambda表达式调用了一个已经存在的静态方法,根据我们第2节表格中的语法,上面的代码可以最终改写成静态方法引用:

 Person[] rosterAsArray = new Person[30];
// 添加数组元素省略 Arrays.sort(rosterAsArray, Person::compareByAge);

  下面这个例子更简单:

 public class Test {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(82,22,34,50,9);
list.sort(Integer::compare);
System.out.println(list);
}
}

  对一个Integer列表进行排序,因为Integer中已经存在静态的比较方法compare(),因此可以直接用静态方法引用的方式来调用 ,运行结果为:

[9, 22, 34, 50, 82]

3.2 实例方法引用

  实例方法引用,顾名思义就是调用已经存在的实例的方法,与静态方法引用不同的是类要先实例化,静态方法引用类无需实例化,直接用类名去调用。

 @Data
class User { private String name;
private Integer age; public User(String name, Integer age) {
this.name = name;
this.age = age;
}
} public class TestInstanceReference { public static void main(String[] args) { TestInstanceReference test = new TestInstanceReference();
User user = new User("欧阳峰",32);
Supplier<String> supplier = () -> user.getName();
System.out.println("Lambda表达式输出结果:" + supplier.get()); Supplier<String> supplier2 = user::getName;
System.out.println("实例方法引用输出结果:" + supplier2.get());
}
}

  输出结果:

Lambda表达式输出结果:欧阳峰
实例方法引用输出结果:欧阳峰

3.3 对象方法引用

  若Lambda参数列表中的第一个参数是实例方法的参数调用者,而第二个参数是实例方法的参数时,可以使用对象方法引用。

String的equals()方法:

 public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
 public static void main(String[] args) {

    BiPredicate<String,String> bp = (x, y) -> x.equals(y);
BiPredicate<String,String> bp1 = String::equals; boolean test = bp1.test("xy", "xx");
System.out.println(test);
}

  BiPredicate的test()方法接受两个参数,x和y,具体实现为x.equals(y),满足Lambda参数列表中的第一个参数是实例方法的参数调用者,而第二个参数是实例方法的参数,因此可以使用对象方法引用。

3.4 构造方法引用

  注意:需要调用的构造器的参数列表要与函数式接口中抽象方法的参数列表保持一致。

  如:要获取一个空的User列表:

 Supplier<List<User>> userSupplier = () -> new ArrayList<>();
List<User> user = userSupplier.get(); Supplier<List<User>> userSupplier2 = ArrayList<User>::new; // 构造方法引用写法
List<User> user2 = userSupplier.get();

  至此,方法引用讲完了,下一章节将讲解Stream API。

  

Java8新特性之二:方法引用的更多相关文章

  1. Java8新特性系列-默认方法

    Java8 Interface Default and Static Methods 原文连接:Java8新特性系列-默认方法 – 微爱博客 在 Java 8 之前,接口只能有公共抽象方法. 如果不强 ...

  2. 乐字节-Java8新特性-接口默认方法

    总概 JAVA8 已经发布很久,而且毫无疑问,java8是自java5(2004年发布)之后的最重要的版本.其中包括语言.编译器.库.工具和JVM等诸多方面的新特性. Java8 新特性列表如下: 接 ...

  3. java8新特性(二)_lambda表达式

    最近一直找java8相关新特性的文章,发现都太没有一个连贯性,毕竟大家写博客肯定都有自己的侧重点,这里找到一本书,专门介绍java8新特性的,感觉大家可以看看<写给大忙人看的JavaSE8> ...

  4. 乐字节-Java8新特性-接口默认方法之Stream流(下)

    接上一篇:<Java8新特性之stream>,下面继续接着讲Stream 5.流的中间操作 常见的流的中间操作,归为以下三大类:筛选和切片流操作.元素映射操作.元素排序操作: 操作 描述 ...

  5. Java8新特性——StreamAPI(二)

    1. 收集器简介 收集器用来将经过筛选.映射的流进行最后的整理,可以使得最后的结果以不同的形式展现. collect方法即为收集器,它接收Collector接口的实现作为具体收集器的收集方法. Col ...

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

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

  7. Java8新特性(二)——强大的Stream API

    一.强大的Stream API 除了Lambda表达式外,Java8另外一项重大更新便是位于java.util.stream.*下的Stream API Stream 是 Java8 中处理集合的关键 ...

  8. Java8新特性——接口默认方法

    Java 8 新增了接口的默认方法. 简单说,默认方法就是接口可以有实现方法,而且不需要实现类去实现其方法. 我们只需在方法名前面加个default关键字即可实现默认方法. 为什么要有这个特性? 首先 ...

  9. Java8新特性(二)之函数式接口

    .subTitle { background: rgba(51, 153, 0, 0.66); border-bottom: 1px solid rgba(0, 102, 0, 1); border- ...

随机推荐

  1. mybatis源码解读(三)——数据源的配置

    在mybatis-configuration.xml 文件中,我们进行了如下的配置: <!-- 可以配置多个运行环境,但是每个 SqlSessionFactory 实例只能选择一个运行环境常用: ...

  2. va_start,va_arg,va_end的使用

    一.在C中,当我们无法列出传递函数的所有实参的类型和数目时,可以用省略号指定参数表. void fun(...); void fun(parm_list,...); #include <stdi ...

  3. Spring Boot 发送邮件

    需求 最近因为业务的变更,需要对老用户进行发送邮件处理.目前市面上也有很多代发邮件的接口,可以接入.由于量不是特别大,放弃了这个途径.改用我们自己通过 smtp 发送邮件来处理. 技术选择 Java ...

  4. iOS 波浪效果的实现

    iOS 波浪效果的实现 p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 14.0px Menlo; color: #4f8187; background-c ...

  5. R画网络图

    R  画网络图 目的:用R做生信分析,画基因样本的网络图,从中观察样本的致病性情况. 一.所用到的包 library(tidyr) library(ggplot2) library(reshape2) ...

  6. 网络营销行业十大看了就想吐的“滥词”

    网络营销行业在国内的互联网界已"猖獗"数年之久,它是一个让企业爱让用户恨的行业.有互联网的地方,就有网络营销的机会,有了机会就有了相关产业的存在,只不过是业大业小的问题.但是随着互 ...

  7. Preload,Prefetch 和它们在 Chrome 之中的优先级

    前言 上周五到的时候,想起之前在手游平台上有处理dns-prefetch的优化,那这篇分享的就更仔细了.今日早读文章由@gy134340翻译并授权分享. 正文从这开始- 今天我们来深入研究一下 Chr ...

  8. 并发库应用之九 & 到时计数器CountDownLatch应用

    申明:CountDownLatch好像倒计时计数器,调用CountDownLatch对象的countDown方法就将计数器减1,当到达0时,所有等待者就开始执行. java.util.concurre ...

  9. Ruby类

    Ruby类 类定义 #!/usr/bin/ruby class Sample def hello puts "Hello Ruby!" end end # 使用上面的类来创建对象 ...

  10. hessian在ssh项目中的配置

    一. 在服务端发布一个web项目 1.创建一个动态的web项目,并导入hessian的jar包 2. 在服务端的crm项目中创建接口 package cn.rodge.crm.service;impo ...