方法引用(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. 160428、JavaScript知识总结—cookie及其应用

    一.cookie基本介绍 cookie是document的对象.cookie可以使得JavaScript代码能够在用户的硬盘上持久地存储数据,并且能够获得以这种方式存储的数据.cookie还可以用于客 ...

  2. Python3量化技术常用插件

    1. 确定自己的系统为64位版本 2. 下载安装Python3 64位版本 如果要使用zipline,建议使用python3.5.另外发现很多东西要求的也是3.5. 主页地址: https://www ...

  3. Django在生产环境中的部署

    基本思路 1.方案:Nginx+uwsgi 这样大体的流程是:nginx作为服务器最前端,负责接收client的所有请求,统一管理.静态请求由Nginx自己处理.非静态请求通过uwsgi传递给Djan ...

  4. 前端 Dom 直接选择器

    文档对象模型(Document Object Model,DOM)是一种用于HTML和XML文档的编程接口.它给文档提供了一种结构化的表示方法,可以改变文档的内容和呈现方式.我们最为关心的是,DOM把 ...

  5. C++入门(2)

    第一个程序,输入输出: #include <iostream> using namespace std; int main() { cout << "Hello, w ...

  6. Spark如何写入HBase/Redis/MySQL/Kafka

    一些概念 一个partition 对应一个task,一个task 必定存在于一个Executor,一个Executor 对应一个JVM. Partition 是一个可迭代数据集合 Task 本质是作用 ...

  7. 转Hibernate 一对多关联的CRUD__@ManyToOne(cascade=(CascadeType.ALL))

    一:Group和Users两个类 假定一个组里有n多用户,但是一个用户只对应一个用户组. 1.所以Group对于Users是“一对多”的关联关系@OneToMany Users对于Group是“多对一 ...

  8. PAT 1077 Kuchiguse [一般]

    1077 Kuchiguse (20 分) The Japanese language is notorious for its sentence ending particles. Personal ...

  9. matplotlib对LaTeX数学公式的支持

    Matlplotlib对LaTeX有一定的支持,如果记得使用raw字符串语法会很自然: xlabel(r"x2y4x2y4") 在matplotlib里面,可以使用LaTex的命令 ...

  10. python 之操作mysql 数据库实例

    对于python操作mysql 数据库,具体的步骤应为: 1. 连接上mysql host 端口号 数据库 账号 密码2. 建立游标3. 执行sql(注意,如果是update,insert,delet ...