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 方法引用通过方法的名字来指向一个方法. 方法引用可以使语言的构造更紧凑简洁,减少 ...
随机推荐
- Asp.net Session 与Cookie的应用
写程序的很多人都知道的,Session是服务器端的东西而Cooike是客户端的东西.因为B/S模式是无状态模式,它们的应用都是要存储客户端的某些登录或是加密的信息. Session存在于服务器端,当然 ...
- Android的px、dp和sp
Android的px.dp和sppx: 即像素,1px代表屏幕上一个物理的像素点:偶尔用到px的情况,是需要画1像素表格线或阴影线的时候. dp: 这个是最常用但也最难理解的尺寸单位.它与“像素密度” ...
- MySql基础整理
http://hovertree.com/menu/mysql/ use abccs;select * from mytable2 limit 3,4;call sp_name1(1,@nn);sel ...
- TINYINT,SMALLINT,MEDIUMINT,INT,INTEGER,BIGINT;text,longtext,mediumtext,ENUM,SET等字段类型区别
http://www.path8.net/tn/archives/951 MySQL支持大量的列类型,它可以被分为3类:数字类型.日期和时间类型以及字符串(字符)类型.本节首先给出可用类型的一个概述, ...
- [python拾遗]文件操作
文件操作 1.open()函数 open()函数主要用于文件处理,一般分为下面3个过程: 1.打开文件 2.操作文件 3.关闭文件 常见的格式示例: f = open('note.txt','r') ...
- Oracle常用
Oracle恢复误删的数据或表,解除锁定SQL或table 转载于: http://renjie120.iteye.com/ 注释:本文转自网络,转载请注明注意:数据库版本是10g,不过大部分9i ...
- Android总结篇系列:Android Service
Service通常总是称之为“后台服务”,其中“后台”一词是相对于前台而言的,具体是指其本身的运行并不依赖于用户可视的UI界面,因此,从实际业务需求上来理解,Service的适用场景应该具备以下条件: ...
- java集合-hashCode
hashCode 的作用 在 Java 集合中有两类,一类是 List,一类是 Set 他们之间的区别就在于 List 集合中的元素师有序的,且可以重复,而 Set 集合中元素是无序不可重复的.对于 ...
- java内存模型-锁
锁的释放-获取建立的 happens before 关系 锁是 java 并发编程中最重要的同步机制.锁除了让临界区互斥执行外,还可以让释放锁的线程向获取同一个锁的线程发送消息.下面是锁释放-获取的示 ...
- css知多少(7)——盒子模型
1. 引言 从这一节开始,我们就进入本系列的第三部分——css呈现.本部分将描述css在页面的几种布局和呈现的特性.包括两类:文字.块. 第一类——文字.这部分相对比较简单一些,例如设置字号.字体.颜 ...