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 方法引用通过方法的名字来指向一个方法. 方法引用可以使语言的构造更紧凑简洁,减少 ...
随机推荐
- C# 汉字转拼音(支持GB2312字符集中所有汉字)
GB2312标准共收录6763个汉字,其中一级汉字3755个,二级汉字3008个. 分区表示 GB 2312中对所收汉字进行了“分区”处理,每区含有94个汉字/符号.这种表示方式也称为区位码. )- ...
- Guava并发:ListenableFuture与RateLimiter示例
ListenableFuture顾名思义就是可以监听的Future,它是对java原生Future的扩展增强 RateLimiter类似于JDK的信号量Semphore,他用来限制对资源并发访问的线程 ...
- vim 使用说明
=========================================================本使用说明与 把VIM打造成IDE 配套======================= ...
- EL表达式错误attribute items does not accept any expressions
解决方法是将 <%@taglib prefix="c" uri="http://java.sun.com/jstl/core"%> 改成 <% ...
- a标签,img标签,表格
<a></a> a标签,超链接标签 ,引入超链接方式: src="...." target="blank" 打开方式--新页 ...
- Scalaz(55)- scalaz-stream: fs2-基础介绍,fs2 stream transformation
fs2是scalaz-stream的最新版本,沿用了scalaz-stream被动式(pull model)数据流原理但采用了全新的实现方法.fs2比较scalaz-stream而言具备了:更精简的基 ...
- UML类图关系总结
在UML类图中,常见的有以下几种关系: 泛化(Generalization) 实现(Realization) 关联(Association) 聚合(Aggregation) 组合(Compositio ...
- @media自适应宽度
<!DOCTYPE HTML> <html> <head> <meta charset="utf-8"> <meta name ...
- 【html5】Web存储_locaStorage对象的应用
Web存储 html5可以在本地存储用户浏览的数据,数据的存储原理是以 键/值 存储的 存储对象分类 localStorage:没有时间限制的数据存储 sessionStorage:针对一个会话的数据 ...
- angular源码分析:injector.js文件分析——angular中的依赖注入式如何实现的(续)
昨天晚上写完angular源码分析:angular中jqLite的实现--你可以丢掉jQuery了,给今天定了一个题angular源码分析:injector.js文件,以及angular的加载流程,但 ...