译者注:本篇博客翻译自Oracle官方教程《Method References》。作为Java 8 新特性Lambda表达式的引申概念,博主依然采用官方文档的方式来学习这一重要的概念。希望对各位同道有所帮助。

方法引用

使用Lambda表达式创建匿名方法。但是,有时候Lambda表达式什么都没做,仅仅是调用了一个已经存在的方法。这种情况下,引用已存在方法的方法名通常是更清晰的。方法引用允许你这么做,它是一种简洁的、可读性强的有名方法的Lambda表达式。

再次思考我们在Lambda 表达式部分(即上一篇翻译《Java8————Lambda表达式(二)》)中讨论的Person类:

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

假设你的应用中的成员全都包含在一个数组中,并且你希望把他们以年龄进行排序。你可以使用下面的代码:

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

调用的sort方法的方法签名(译者注:方法签名是包含方法名、参数列表等在内的方法信息)如下:

static <T> void sort(T[] a, Comparator<? super T> c)

注意,Comparator接口是一个函数接口。因此,你可以使用Lambda表达式而不是去定义并随后创建一个实现了Comparator的类的实例:

Arrays.sort(rosterAsArray,(Person a, Person b) -> {return a.getBirthday().compareTo(b.getBirthday());}
);

但是,比较两个Person对象生日的方法已经存在于Person.compareByAge方法当中。你可以Lambda表达式的body中调用:

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

因为这个Lambda表达式调用一个存在的方法,因此,你可以使用方法引用来代替Lambda表达式:

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

方法引用 Person::compareByAge语义上与Lambda表达式(a, b) -> Person.compareByAge(a, b) 是一样的。都具备以下特性:

1、它的参数列表:(Person , Person)从Comparator<Person>.compare复制过来。

2、它的主体调用方法Person.compareByAge()

方法引用的种类

有如下四种方法引用:

种类 举例
Reference to a static method ContainingClass::staticMethodName
Reference to an instance method of a particular object containingObject::instanceMethodName
Reference to an instance method of an arbitrary object of a particular type ContainingType::methodName
Reference to a constructor ClassName::new
  • 静态方法引用

方法引用如:Person::compareByAge 就是对静态方法的引用。

  • 特定对象的实例方法引用

下面的例子就是对特定对象的实例方法引用:

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

方法引用:myComparisonProvider::compareByName,调用了myComparisonProvider对象的方法compareByName。JRE会推断出方法的参数类型,这个例子中是(Person, Person)。

  • 特定类型的任意对象的实例方法引用

下面的例子是特定类型的任意对象的实例方法引用:

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

与Lambda表达式等价的方法引用 String::compareToIgnoreCase 有一个正式的参数列表:(String a, String b), a 和b 都是用来更好的描述这个例子的任意的名称。这个方法引用会调用方法:a.compareToIgnoreCase(b)。

  • 构造器的方法引用

你可以像使用静态方法引用的方式那样使用new关键字来引用构造器。下面的方法将元素从一个集合中拷贝到另一个集合中。

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表达式调用transferElements()方法:

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

你可以像下面这样使用构造器引用来取代Lambda表达式:

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

Java编译器会推断出你希望创建一个包含元素类型为Person的HashSet集合。你可以像下面这样来指定,二选一。

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

Java8————方法引用相关推荐

  1. java8方法引用符合_java8,方法引用

    当我们使用lambda表达式去创建一个匿名方法时,有时我们并没有做什么事情,仅仅是使用了对象中一个存在的方法.这种情况下,通过对象的方法名就能够很明显的推断出要使用 的方法,java8中的方法引用能够 ...

  2. java8 方法引用详解_Java8中如何通过方法引用获取属性名详解

    前言 在我们开发过程中常常有一个需求,就是要知道实体类中Getter方法对应的属性名称(Field Name),例如实体类属性到数据库字段的映射,我们常常是硬编码指定 属性名,这种硬编码有两个缺点. ...

  3. Java8 方法引用

    概述 方法引用是用来直接访问类或实例阴茎存在的方法或者构造方法.它需要由兼容的函数式接口(lambda表达式中用到的接口)构成的目标类型上下文. 有时候, 当我们想要实现一个函数式接口的方法, 但是已 ...

  4. java8 方法引用好处_Java 8方法引用

    原标题:Java 8方法引用 方法引用有助于通过名称指向方法.使用"::"符号描述方法引用.方法引用可以用来指出以下类型的方法 - 静态方法 实例方法 使用new运算符的构造函数( ...

  5. java8方法引用符合_Java8 方法引用和构造方法引用

    如果不熟悉Java8新特性的小伙伴,初次看到函数式接口写出的代码可能会是一种懵逼的状态,我是谁,我在哪,我可能学了假的Java,(・∀・(・∀・(・∀・*),但是语言都是在进步的,就好比面向对象的语言 ...

  6. Java8 方法引用和Stream流

    Stream 流API 什么是流 流的操作种类 流的操作过程 使用流 创建流 集合 数组 值 筛选 filter 去重 distinct 截取 limit 跳过 skip 映射 map 合并多个流 是 ...

  7. 【java8新特性】——方法引用(四)

    一.简介 方法引用是java8的新特性之一, 可以直接引用已有Java类或对象的方法或构造器.方法引用与lambda表达式结合使用,可以进一步简化代码. 来看一段简单代码: public static ...

  8. 引用java8里的方法_Java8中方法引用的使用详解

    1. 引言 Java8中最受广大开发中喜欢的变化之一是因为引入了 lambda 表达式,因为这些表达式允许我们放弃匿名类,从而大大减少了样板代码,并提高了可读性. 方法引用是lambda表达式的一种特 ...

  9. 【Java8新特性】浅谈方法引用和构造器引用

    写在前面 Java8中一个很牛逼的新特性就是方法引用和构造器引用,为什么说它很牛逼呢?往下看! 方法引用 当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用!这里需要注意的是:实现抽 ...

最新文章

  1. 那些为了学技术而离婚、私奔的大佬们运营的公众号有哪些?
  2. 目标检测--Object Detection via Aspect Ratio and Context Aware
  3. AtCoder AGC002E Candy Piles (博弈论)
  4. openCV—Python(6)—— 图像算数与逻辑运算
  5. python 中cookie_Python 处理Cookie的菜鸟教程(一)Cookie库
  6. 全志 移除屏幕超时选项 Patch
  7. 解决Eclipse代码分析插件SonarLint在Console输出乱码问题
  8. 永磁同步电机三相等效电路图_永磁同步电动机三相坐标系的数学模型
  9. Promise 的基本使用 与 Ajax的jQuery封装
  10. [剑指offer]面试题第[63]题[Leetcode][第121题][JAVA][买卖股票的最佳时机][动态规划][暴力]
  11. 超全超详细的HTTP状态码大全
  12. C#网络编程(Socket编程)
  13. Qt实现 QQ好友列表QToolBox
  14. linux 下修复坏u盘启动不了怎么办,U盘打不开并不是坏了, 用这两个命令, 轻松修复里面的文件...
  15. 指数增长模型matlab代码_多元思维模型1:复利模型——拥抱指数增长
  16. 使用node.js构建一个web服务器(适合自学)
  17. 2011计算机一级a,2011河北省大学生计算机一级A卷操作步骤
  18. sitemap-php生成网站地图
  19. C语言程序设计第六次作业——循环结构(2)
  20. mysql查询每个部门的最高和最低工资_SQL数据库 计算出每个部门的平均工资 最高工资和最低工资 语法怎么写?...

热门文章

  1. 视频人脸检测——OpenCV版(三)
  2. JS判断文本框中只能输入数字和小数点
  3. 【STM32】修改芯片型号后报 Error 的解决方案
  4. 玛酷机器人课程视频_建阳玛酷机器人丨2019WRO机器人比赛凯旋而归!
  5. latex在texstudio中编译tex文件不显示攻读硕士学位期间取得的成果
  6. git两个账号切换_Git切换账号方法
  7. mysql磁盘无法挂载,linux – 无法挂载磁盘(VFS:找不到ext4文件系统)
  8. 【IDEA】IDEA中使用git将项目上传到码云上
  9. MYSQL数据库实验三多表查询_数据库之 MySQL --- 数据处理 之多表查询 (三)
  10. 腾讯视频APP如何提交反馈