方法引用(Method Reference)

上一篇中记录了Lambda表达式,其可以创建匿名方法。当Lambda表达式只是调用一个存在的方法时,可以采用方法引用(JDK8具有的特性)。如下:

 public class Person {

     public enum Sex {
MALE, FEMALE
} String name;
LocalDate birthday;
Sex gender;
String emailAddress;
int age; public int getAge() {
return age;
} public LocalDate getBirthday() {
return birthday;
} public static int compareByAge(Person a, Person b) {
return a.birthday.compareTo(b.birthday);
}

假设需要对一组人员按年龄进行排序,可以采用下边的方式,将人员数组与实现的比较器,传递给Array.sort方法:

 Person[] rosterAsArray = roster.toArray(new Person[roster.size()]);

 class PersonAgeComparator implements Comparator<Person> {
public int compare(Person a, Person b) {
return a.getBirthday().compareTo(b.getBirthday());
}
} Arrays.sort(rosterAsArray, new PersonAgeComparator()); 

当然,可以将PersonAgeComparator的实现采用Lambda表达式,如下:

  Arrays.sort(rosterAsArray, (a,b) -> a.birthday.compareTo(b.birthday)); 

Person类中已经包含根据年龄的比较compareByAge,只需要在Lambda表达式体中直接调用即可

 Arrays.sort( rosterAsArray, (a,b) -> Person.compareByAge(a,b)); 

由于Lambda表达式调用一个已经存在的方法,可以使用方法引用代替Lambda表达式,如下:

 Arrays.sort(rosterAsArray, Person::compareByAge); 

其中 ,Person::compareByAge 与 (a, b) -> Person.compareByAge(a, b)是等价的。(1)其参数拷贝于Comparator<Person>.compare,即 (Person, Person);(2)body将调用Person.compareByAge。

方法引用类别

有4种方法引用,如下:

  • 引用静态方法,如 ContainingClass::staticMethodName;
  • 引用实例方法,如 containingObject::instanceMethodName;
  • 引用特殊类型对象的方法,如 ContainingType::methodName;
  • 引用构造函数,如 ClassName::new。

(1)引用静态方法

上文中的例子即为静态方法引用。

(2)引用实例方法

即通过类的实例引用方法,如下:

 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); 

(3)引用特殊类型对象的方法

以String为例:

 String[] stringArray = { "Barbara", "James", "Mary", "John",
"Patricia", "Robert", "Michael", "Linda" };
Arrays.sort(stringArray, String::compareToIgnoreCase); 

(4)引用构造函数

假设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;

其中Supplier包含一个get方法,只返回一个空的集合对象,并且不需要任何参数,可以使用Lambda表达式实现,如下:

 Set<Person> rosterSetLambda =
transferElements(roster, () -> { return new HashSet<>(); }); 

此时可以采用引用构造函数的方法,如下:

Set<Person> rosterSet = transferElements(roster, HashSet::new);
//或
Set<Person> rosterSet = transferElements(roster, HashSet<Person>::new); 

总结

  • 对于Lambda表达式,当只是调用一个已存在的方法时,可以采用方法引用的方式实现,编译器会自行翻译

参考

Method references

Java学习笔记-方法引用的更多相关文章

  1. JAVA学习笔记--方法中的参数调用是引用调用or值调用

    文献来源:<JAVA核心技术卷Ⅰ>,第4章第5节 (没有相关书籍的可看传送门) ps:测试demo因为偷懒,用的是String对象 结论:Java使用的是对象的值引用.即将任何对象所在内存 ...

  2. java学习笔记 --- 方法

    一.方法  (1)方法:就是完成特定功能的代码块.   注意:在很多语言里面有函数的定义,而在Java中,函数被称为方法.  (2)格式:   修饰符 返回值类型 方法名(参数类型 参数名1,参数类型 ...

  3. Java学习笔记day03_引用数据类型

    1.引用数据类型 步骤: 1. 导包   2. 创建引用类型变量 类型 变量名 = new 类型名();   3. 使用数据类型的功能 变量名.功能名(); 如Scanner类: import jav ...

  4. 0030 Java学习笔记-面向对象-垃圾回收、(强、软、弱、虚)引用

    垃圾回收特点 垃圾:程序运行过程中,会为对象.数组等分配内存,运行过程中或结束后,这些对象可能就没用了,没有变量再指向它们,这时候,它们就成了垃圾,等着垃圾回收程序的回收再利用 Java的垃圾回收机制 ...

  5. Java学习笔记之---方法和数组

    Java学习笔记之---方法与数组 (一)方法 (1)什么是方法? 方法是解决一类问题的步骤的有序组合 方法包含于类或对象中 方法在程序中被创建,在其他地方被引用 (2)方法的优点 使程序变得更简短而 ...

  6. java学习笔记5--类的方法

    接着前面的学习: java学习笔记4--类与对象的基本概念(2) java学习笔记3--类与对象的基本概念(1) java学习笔记2--数据类型.数组 java学习笔记1--开发环境平台总结 本文地址 ...

  7. Java学习笔记(04)

    Java学习笔记(04) 如有不对或不足的地方,请给出建议,谢谢! 一.对象 面向对象的核心:找合适的对象做合适的事情 面向对象的编程思想:尽可能的用计算机语言来描述现实生活中的事物 面向对象:侧重于 ...

  8. 0032 Java学习笔记-类加载机制-初步

    JVM虚拟机 Java虚拟机有自己完善的硬件架构(处理器.堆栈.寄存器等)和指令系统 Java虚拟机是一种能运行Java bytecode的虚拟机 JVM并非专属于Java语言,只要生成的编译文件能匹 ...

  9. 0028 Java学习笔记-面向对象-Lambda表达式

    匿名内部类与Lambda表达式示例 下面代码来源于:0027 Java学习笔记-面向对象-(非静态.静态.局部.匿名)内部类 package testpack; public class Test1{ ...

随机推荐

  1. MySQL按照汉字的拼音排序、按照首字母分类

    项目中有时候需要按照汉字的拼音排序,比如联系人列表.矿物分类等,有的还需要按拼音字母从A到Z分类显示. 如果存储汉字的字段编码使用的是GBK字符集,因为GBK内码编码时本身就采用了拼音排序的方法(常用 ...

  2. 任务调度quartz整理

    一张图,了解quartz运行机制: 此图表示:Scheduler是容器,Trigger是多个触发器,jobDetail是多个任务,Calendar是多个日历. jobDetail任务,需要指定类实现J ...

  3. UVA12470—Tribonacci (类似斐波那契,简单题)

    题目链接:https://vjudge.net/problem/UVA-12470 题目意思:我们都知道斐波那契数列F[i]=F[i-1]+F[i-2],现在我们要算这样的一个式子T[i]=T[i-1 ...

  4. linux下安装JDK,及配置环境变量

    首先去官网https://www.oracle.com/technetwork/java/javase/downloads/index.html下载最新的JDK版本: 以下操作在root用户下操作 第 ...

  5. LeetCode之Symmetric Tree

    </pre>Given a binary tree, check whether it is a mirror of itself (ie, symmetric around its ce ...

  6. LeetCode_链表操作1—Swap Nodes in Pairs

    Given a linked list, swap every two adjacent nodes and return its head. For example, Given 1->2-& ...

  7. golang几种post方式

    用golang进行http请求类型多了,总结备忘一下. 1.普通的post\get请求 var r http.Request r.ParseForm() r.Form.Add("uuid&q ...

  8. 在django中实现支付宝支付(支付宝接口调用)

    支付宝支付 正式环境:用营业执照,申请商户号,appid 测试环境:沙箱环境:https://openhome.alipay.com/platform/appDaily.htm?tab=info 支付 ...

  9. Python 之父谈放弃 Python:我对核心成员们失望至极!

    Python 之父讲述退位原因,以及 Python 的未来将何去何从. ​ 在 Python 社区,Python 的发明者 Guido Van Rossum 被称为 “仁慈的终生独裁者”(BDFL,B ...

  10. .Net站点架构设计(八)測试

    .Net站点架构时间(八)測试 一般而言.总体測试策略是:先针对部分系统进行性能及压力測试,得到各部分的峰值处理性能:再模拟总体流程測试,此时倒不用依照峰值跑,重点測试总体业务流程及业务预期负荷. 在 ...