Java8————方法引用

译者注:本篇博客翻译自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 methodContainingClass::staticMethodName
Reference to an instance method of a particular objectcontainingObject::instanceMethodName
Reference to an instance method of an arbitrary object of a particular typeContainingType::methodName
Reference to a constructorClassName::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);

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/558919.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

设计模式---适配器设计模式

设计模式---适配器设计模式 什么事适配器&#xff1a; 1. 在使用监听的时候&#xff0c;需要定义一个类事件监听器接口 2. 通常接口中有多个方法&#xff0c;而程序中不一定所有的方法都用到&#xff0c;但又必须重写&#xff0c;很繁琐 3. 适配器简化了这些操作&#xff0c…

Java并发编程实战————售票问题

引言 现有一个需求如下&#xff1a; 有10000张火车票&#xff0c;每张票都有一个编号&#xff0c;同时有10个窗口对外售票&#xff0c;如何确保车票的正常售卖&#xff1f; 程序一&#xff1a;使用List 问题的解决办法都是从我们最最熟悉的角度思考。程序一&#xff0c;我们…

多线程相关知识

多线程相关知识 两个线程进行通信&#xff1a;通过等待&#xff08;wait&#xff09;唤醒&#xff08;notify&#xff09;机制 三个或三个以上线程进行通信&#xff1a;通过notifyAll&#xff08;&#xff09;方法 /* * 1. 在同步代码块中&#xff0c;用哪个对象锁&#xff0c…

Eclipse集成PyDev5.2.0开发插件

引言 在进行Python学习的时候&#xff0c;希望不使用IDLE进行开发&#xff0c;但是其他的IDE如PyCharm可能需要一段短暂时间的上手&#xff0c;因为开发过Java&#xff0c;所以使用能够集成到Eclipse上的PyDev插件进行开发应该会好一些。 但是在安装PyDev的时候发生了一些问题…

PostMan 四种常见的 POST 提交数据方式

HTTP/1.1 协议规定的 HTTP 请求方法有 OPTIONS、GET、HEAD、POST、PUT、DELETE、TRACE、CONNECT 这几种。其中 POST 一般用来向服务端提交数据&#xff0c;本文主要讨论 POST 提交数据的几种方式。 协议规定 POST 提交的数据必须放在消息主体&#xff08;entity-body&#xff0…

Java并发编程实战————对象的组合

引言 对象的组合&#xff0c;是《Java Concurrency in Practice》中第四章引入的课题。这并不是一个并发的概念。 为了可以将现有的线程安全组件组合为更大规模的组件或程序&#xff0c;而不是每次内存访问都进行分析以确保程序是线程安全的。这一章将介绍一些组合模式&#…

史上最真实行业鄙视链

本文转载自菜鸟教程的微信公众号&#xff0c;原文链接&#xff1a;https://mp.weixin.qq.com/s/d9cdtq8y4Msq-_ZNof-iuw 引言 作为程序员的一份子&#xff0c;掌握好各个生态系统中的鄙视链&#xff0c;可以写出更加符合改变世界要求的代码。掌握了鄙视链&#xff0c;就掌握了…

如何快速理清大型项目业务逻辑

引言 本篇文章为了探讨如何快速上手一个大型项目。针对经验尚浅需要快速接手一个项目的开发人员。 当他们拿到一个大型程序后&#xff0c;他们便开始一句一句的阅读分析&#xff0c;夜以继日&#xff0c;悬梁刺股。可结果依然不理想&#xff0c;往往进入以下状态&#xff1a;…

权限验证框架Shiro

权限验证框架Shiro&#xff1a; Shiro简介 什么是Shiro&#xff1a; shiro是一个强大易用的Java安全框架&#xff0c;提供了认证&#xff0c;授权&#xff0c;加密&#xff0c;回话管理等功能&#xff1b; 认证&#xff08;Authentication&#xff09;&#xff1a;用户身份识别…

Linux——less指令常用操作

引言 对于生产环境、测试环境中的日志文件&#xff0c;我们可以通过less指令来进行查看并通过关键字进行查找。less命令的含义是&#xff1a;分屏查看文件内容。 它要比more命令更加强大&#xff0c;less在显示文件内容时&#xff0c;并不是一次将整个文件加载之后才显示&…

Mybatis从入门到精通上篇

Mybatis从入门到精通上篇&#xff1a; 学习过的持久层框架&#xff1a;DBUtils , Hibernate Mybatis就是类似于hibernate的orm持久层框架。 Mybatis介绍&#xff1a; Mybatis是面向sql的持久层框架&#xff0c;他封装了jdbc访问数据库的过程&#xff0c;我们开发&#xff0c;只…

Eclipse使用————Working Set工作集

引言 经常看到在设置项目的时候&#xff0c;如导入项目&#xff0c;新建项目等看到对话框的下方有一个“add to working set”复选框&#xff0c;为了弄清这个working set&#xff0c;我们就来好好了解一下Eclipse 的working set功能。 Working Set&#xff1f; Eclipse中通…

Mybatis从入门到精通下篇

Mybatis从入门到精通下篇&#xff1a; 输入类型&#xff1a; 输出类型&#xff1a; ResultMap&#xff1a; 动态sql&#xff1a; if标签&#xff1a; where标签&#xff1a; sql片段&#xff1a; foreach标签&#xff1a; 关联查询&#xff1a; 以订单作为主体&#xff1a; 一…

爱上进制转换练习

引言 对于可能接触到通讯行业或是物联网的开发工作者&#xff0c;一般会面对十进制、二进制、十六进制的转换工作&#xff0c;不仅仅是体现在代码上&#xff0c;有时候也需要用肉眼来进行快速的转化&#xff0c;以获取协议指令中的信息。 今天通过简单的整理&#xff0c;特此…

Sprint Boot————@Qualifier、@Primary

引言 使用Autowired自动注入时&#xff1a; 如果注入的接口有多个实现类&#xff0c;如下所示&#xff1a; 那么如果不指定具体是哪个实现类的Bean&#xff0c;在Spring Boot启动时就会发生异常&#xff08;下图请点击查看&#xff09;&#xff1a; 异常的描述信息非常简单&am…

SpringMVC教程上篇

SpringMVC教程上篇 SpringMVC优势&#xff1a; SpringMVC代码执行流程&#xff1a; 框架结构&#xff1a; 架构流程&#xff1a; 组件说明&#xff1a; SpringMVC与Mybatis整合 ! 效果: 开发流程&#xff1a;

Eclipse使用————生成Get/Set、toString快捷键(不使用鼠标)

引言 除了鼠标右键空白处—>source选择我们需要的操作之外是否还有更快捷的不需要鼠标的操作呢&#xff1f; 如何快速的通过键盘来生成get、set方法&#xff1f;如何快速的通过键盘生成toString方法&#xff1f;如何快速的通过键盘生成需要实现的父类方法呢&#xff1f; …

SpringMVC教程下篇

SpringMVC教程下篇 内容包括&#xff1a; 绑定数组&#xff1a; 将表单数据绑定到list&#xff1a; RequestMapping注解的三种用法&#xff1a; Controller方法返回值&#xff1a; 乱码问题总结 异常处理&#xff1a; 照片上传&#xff1a; RESTFUL支持&#xff…

Spring Boot面试杀手锏————自动配置原理

引言 不论在工作中&#xff0c;亦或是求职面试&#xff0c;Spring Boot已经成为我们必知必会的技能项。除了某些老旧的政府项目或金融项目持有观望态度外&#xff0c;如今的各行各业都在飞速的拥抱这个已经不是很新的Spring启动框架。 当然&#xff0c;作为Spring Boot的精髓…

为什么要坚持写博客

引言 断断续续地写博客已经有一段时间了&#xff0c;作为一个Java中级开发工程师&#xff0c;工作了三年多也算渐渐入了门。不得不说&#xff0c;博客给我的改变是非常大的&#xff0c;那么作为一个技术人员&#xff0c;为什么我觉得必须要坚持写博客&#xff1f;下面&#xf…