JAVA 8 方法引用 - Method References
什么是方法引用
简单地说,就是一个Lambda表达式。在Java 8中,我们会使用Lambda表达式创建匿名方法,但是有时候,我们的Lambda表达式可能仅仅调用一个已存在的方法,而不做任何其它事,对于这种情况,通过一个方法名字来引用这个已存在的方法会更加清晰,Java 8的方法引用允许我们这样做。方法引用是一个更加紧凑,易读的Lambda表达式,注意方法引用是一个Lambda表达式,其中方法引用的操作符是双冒号"::"。
方法引用例子
先看一个例子
首先定义一个Person类,如下:
package methodreferences; import java.time.LocalDate; public class Person
{ public Person(String name, LocalDate birthday)
{
this.name = name;
this.birthday = birthday;
} String name;
LocalDate birthday; public LocalDate getBirthday()
{
return birthday;
} public static int compareByAge(Person a, Person b)
{
return a.birthday.compareTo(b.birthday);
} @Override
public String toString()
{
return this.name;
}
}
假设我们有一个Person数组,并且想对它进行排序,这时候,我们可能会这样写:
原始写法
package methodreferences; import java.time.LocalDate;
import java.util.Arrays;
import java.util.Comparator; public class Main
{ static class PersonAgeComparator implements Comparator<Person> {
public int compare(Person a, Person b) {
return a.getBirthday().compareTo(b.getBirthday());
}
} public static void main(String[] args)
{
Person[] pArr = new Person[]{
new Person("003", LocalDate.of(2016,9,1)),
new Person("001", LocalDate.of(2016,2,1)),
new Person("002", LocalDate.of(2016,3,1)),
new Person("004", LocalDate.of(2016,12,1))}; Arrays.sort(pArr, new PersonAgeComparator()); System.out.println(Arrays.asList(pArr));
}
}
其中,Arrays类的sort方法定义如下:
public static <T> void sort(T[] a, Comparator<? super T> c)
这里,我们首先要注意Comparator接口是一个函数式接口,因此我们可以使用Lambda表达式,而不需要定义一个实现Comparator接口的类,并创建它的实例对象,传给sort方法。
使用Lambda表达式,我们可以这样写:
改进一,使用Lambda表达式,未调用已存在的方法
package methodreferences; import java.time.LocalDate;
import java.util.Arrays; public class Main
{ public static void main(String[] args)
{
Person[] pArr = new Person[]{
new Person("003", LocalDate.of(2016,9,1)),
new Person("001", LocalDate.of(2016,2,1)),
new Person("002", LocalDate.of(2016,3,1)),
new Person("004", LocalDate.of(2016,12,1))}; Arrays.sort(pArr, (Person a, Person b) -> {
return a.getBirthday().compareTo(b.getBirthday());
}); System.out.println(Arrays.asList(pArr));
}
}
然而,在以上代码中,关于两个人生日的比较方法在Person类中已经定义了,因此,我们可以直接使用已存在的Person.compareByAge方法。
改进二,使用Lambda表达式,调用已存在的方法
package methodreferences; import java.time.LocalDate;
import java.util.Arrays; public class Main
{ public static void main(String[] args)
{
Person[] pArr = new Person[]{
new Person("003", LocalDate.of(2016,9,1)),
new Person("001", LocalDate.of(2016,2,1)),
new Person("002", LocalDate.of(2016,3,1)),
new Person("004", LocalDate.of(2016,12,1))}; Arrays.sort(pArr, (a, b) -> Person.compareByAge(a, b)); System.out.println(Arrays.asList(pArr));
}
}
因为这个Lambda表达式调用了一个已存在的方法,因此,我们可以直接使用方法引用来替代这个Lambda表达式,
改进三,使用方法引用
package methodreferences; import java.time.LocalDate;
import java.util.Arrays; public class Main
{ public static void main(String[] args)
{
Person[] pArr = new Person[]{
new Person("003", LocalDate.of(2016,9,1)),
new Person("001", LocalDate.of(2016,2,1)),
new Person("002", LocalDate.of(2016,3,1)),
new Person("004", LocalDate.of(2016,12,1))}; Arrays.sort(pArr, Person::compareByAge); System.out.println(Arrays.asList(pArr));
}
}
在以上代码中,方法引用Person::compareByAge在语义上与Lambda表达式 (a, b) -> Person.compareByAge(a, b) 是等同的,都有如下特性:
- 真实的参数是拷贝自Comparator<Person>.compare方法,即(Person, Person);
- 表达式体调用Person.compareByAge方法;
四种方法引用类型
静态方法引用
我们前面举的例子Person::compareByAge就是一个静态方法引用。
特定实例对象的方法引用
如下示例,引用的方法是myComparisonProvider 对象的compareByName方法;
class ComparisonProvider
{
public int compareByName(Person a, Person b)
{
return a.getName().compareTo(b.getName());
} public int compareByAge(Person a, Person b)
{
return a.getBirthday().compareTo(b.getBirthday());
}
}
ComparisonProvider myComparisonProvider = new ComparisonProvider();
Arrays.sort(rosterAsArray, myComparisonProvider::compareByName);
任意对象(属于同一个类)的实例方法引用
如下示例,这里引用的是字符串数组中任意一个对象的compareToIgnoreCase方法。
String[] stringArray = { "Barbara", "James", "Mary", "John", "Patricia", "Robert", "Michael", "Linda" };
Arrays.sort(stringArray, String::compareToIgnoreCase);
构造方法引用
如下示例,这里使用了关键字new,创建了一个包含Person元素的集合。
Set<Person> rosterSet = transferElements(roster, HashSet<Person>::new);
transferElements方法的定义如下,功能为集合拷贝,
public static <T, SOURCE extends Collection<T>, DEST extends Collection<T>>
DEST transferElements(
SOURCE sourceCollection,
Supplier<DEST> collectionFactory) { DEST result = collectionFactory.get();
for (T t : sourceCollection) {
result.add(t);
}
return result;
}
什么场景适合使用方法引用
当一个Lambda表达式调用了一个已存在的方法
什么场景不适合使用方法引用
当我们需要往引用的方法传其它参数的时候,不适合,如下示例:
IsReferable demo = () -> ReferenceDemo.commonMethod("Argument in method.");
参考资料
http://java8.in/java-8-method-references/
https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html
JAVA 8 方法引用 - Method References的更多相关文章
- Atitit java方法引用(Method References) 与c#委托与脚本语言js的函数指针
Atitit java方法引用(Method References) 与c#委托与脚本语言js的函数指针 1.1. java方法引用(Method References) 与c#委托与脚本语言js ...
- Java 8Lambda之方法引用(Method References)
方法引用分为4类,方法引用也受到访问控制权限的限制,可以通过在引用位置是否能够调用被引用方法来判断.具体分类信息如下: 类型 使用方式 静态方法 ContainingClass::staticMeth ...
- 方法引用(Method References)
* 方法引用的使用 * * 1.使用情境:当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用! * * 2.方法引用,本质上就是Lambda表达式,而Lambda表达式作为函数式接口 ...
- Java 8 新特性-菜鸟教程 (2) -Java 8 方法引用
Java 8 方法引用 方法引用通过方法的名字来指向一个方法. 方法引用可以使语言的构造更紧凑简洁,减少冗余代码. 方法引用使用一对冒号 :: . 下面,我们在 Car 类中定义了 4 个方法作为例子 ...
- Java基础-方法(method)的应用
Java基础-方法(method)的应用 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 方法就是定义在类中,具有特定功能的一段小程序,方法也称为函数(function),方法可以接 ...
- 方法引用(Method reference)和invokedynamic指令详细分析
方法引用(Method reference)和invokedynamic指令详细分析 invokedynamic是jvm指令集里面最复杂的一条.本文将详细分析invokedynamic指令是如何实现方 ...
- Upgrading to Java 8——第二章 Method References(方法引用)
概述 很多java 方法会使用函数式接口作为参数.例如,java.util.Arrays类中的一个sort方法,就接受一个Comparator接口,它就是一个函数式接口,sort方法的签名如下: pu ...
- Java中的函数式编程(四)方法引用method reference
写在前面 我们已经知道,lambda表达式是一个匿名函数,可以用lambda表达式来实现一个函数式接口. 很自然的,我们会想到类的方法也是函数,本质上和lambda表达式是一样的,那是否也可以用类 ...
- Java 8 方法引用
转自:https://www.runoob.com/java/java8-method-references.html 方法引用通过方法的名字来指向一个方法. 方法引用可以使语言的构造更紧凑简洁,减少 ...
随机推荐
- 不可或缺 Windows Native (16) - C++: 函数重载, 缺省参数, 内联函数, 函数模板
[源码下载] 不可或缺 Windows Native (16) - C++: 函数重载, 缺省参数, 内联函数, 函数模板 作者:webabcd 介绍不可或缺 Windows Native 之 C++ ...
- PHP旧系统基于命名空间重构经验
命名空间其实只是一个形式,最终目的是重构代码,但这个过程想要一蹴而就是不可能的. 一开始给了一个伪命题:基于ThinkPHP的重构(不要问为什么).经过一段的实践,发现这是一个大错特错的思维方式,其中 ...
- Thinkphp 用PHPExcel 导入Excel
搞了个简单的Excel导入, 用的是PHPExcel(百科:用来操作Office Excel文档的一个PHP类库, 基于微软的OpenXML标准和PHP语言) 好, 不说了, 开始吧... 首先得有P ...
- 2015暑假多校联合---Friends(dfs枚举)
原题链接 Problem Description There are n people and m pairs of friends. For every pair of friends, they ...
- InfluxDB学习之InfluxDB的HTTP API写入操作
HTTP API也有两种操作:写入和查询,本文就先给大家介绍一下 InfluxDB的HTTP API的写入操作方式. 在InfluxDB学习的上一篇文章:InfluxDB学习之InfluxDB ...
- Maven+Spring+Spring MVC+MyBatis+MySQL,搭建SSM框架环境
项目建设完成之后的结构: 数据库的表结构如下: 环境建设:搭建Maven环境.Tomcat环境.需要MySql 数据库支持,使用的编程工具Eclipse (这些是前期准备): 开始创建工程: 1.创建 ...
- Nginx负载均衡配置实例详解
负载均衡是我们大流量网站要做的一个东西,下面我来给大家介绍在Nginx服务器上进行负载均衡配置方法,希望对有需要的同学有所帮助哦. 负载均衡 先来简单了解一下什么是负载均衡,单从字面上的意思来理解就可 ...
- Java Selenium封装--RemoteWebDriver
package com.selenium.driver; import java.io.File; import java.io.IOException; import java.net.URL; i ...
- IIS 7 托管管道模式 经典模式(Classic) 集成模式(Integrated) 分析与理解
IIS 7.0 支持两种管道模式:一种是IIS 7.0最新提供的集成管道模式,另一种是经典管道模式,经典管道模式是由先前版本的IIS提供的. 我们可以通过应用程序池设置管道模式,这项功能对IIS管理员 ...
- 国际化支持(I18N)
本章译者:@nixil 使用国际化支持(I18N)能够使你的应用根据用户所在地区的不同选择不同的语言.下面介绍如何在引用中使用国际化. 只允许使用UTF-8 Play只支持UTF-8一种字符编码.这是 ...