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 方法引用通过方法的名字来指向一个方法. 方法引用可以使语言的构造更紧凑简洁,减少 ...
随机推荐
- 自己对Debug的一些感悟
A.13-03-06记. 1.当项目中发现bug的时候,首先考虑如何重现,能够重现的bug比较好找寻根源. 2.思考下以前是否发现过类似bug,是否由一些外部配置所决定. 3.有循环时候注意临界条件.
- mysql 批量插入数据
MySQL使用INSERT插入多条记录,应该如何操作呢?下面就为您详细介绍MySQL使用INSERT插入多条记录的实现方法,供您参考. 看到这个标题也许大家会问,这有什么好说的,调用多次INSERT语 ...
- Scalaz(53)- scalaz-stream: 程序运算器-application scenario
从上面多篇的讨论中我们了解到scalaz-stream代表一串连续无穷的数据或者程序.对这个数据流的处理过程就是一个状态机器(state machine)的状态转变过程.这种模式与我们通常遇到的程序流 ...
- Jquery UI 和Easy UI常用插件
一.Jquery的插件简介 (一)什么是插件 插件(Plug-in)是一种遵循一定的应用程序接口规范编写出来的程序,是原有系统平台或应用软件平台功能的一种扩展和补充. 注意!!其只能在程序规定的系统平 ...
- iOS安全笔记
这一篇文章, 加上里面链接的几篇文章(一个百度的, 两个阮一峰的), 全看完应该了解得差不多了 如何打造一个安全的App?这是每一个移动开发者必须面对的问题.在移动App开发领域,开发工程师对于安全方 ...
- html和css的编码规范
HTML和CSS编码规范内容 一.HTML规范 二.CSS规范 三.注意事项: 四.常用的命名规则 五.CSS样式表文件命名 六.文件命名规则 一.HTML规范: 1.代码规范 页面的第一行添加标准模 ...
- jPList – 实现灵活排序和分页功能的 jQuery 插件
jPList 是一个灵活的 jQuery 插件,可以用于任何 HTML 结构的排序,分页和筛选.它支持的数据源包括:PHP + MySQL,ASP.NET + SQL Server,PHP + SQL ...
- 6to5 – 让你即刻体验 ECMAScript 6 编程
ECMAScript 6 是下一代的 ECMAScript 标准.ECMAScript 6 的目标是让 JavaScript 可以用来编写复杂的应用程序.函数库和代码的自动生成器. ES6 是这门语言 ...
- 定制Eclipse IDE之插件篇(一)
上文回顾:定制Eclipse IDE之功能篇(二) 在这篇文章中,我会将我定制eclipse用到的其他插件罗列出来. 一.汉化插件 Eclipse本身是英文显示的,我们能够通过插件汉化. 1. 选择 ...
- javascript 对象初探 (四)--- 内建对象之旅之Array
我们不要去纠结神马是内建对象,神马是內建构造器.到后来你们便会发现其实她们都是对象. Array()是一个构建数组的內建构造器函数: var arr = new Array(); 与下面的是等效的: ...