Java学习:方法的引用
方法引用(Method references)
lambda表达式允许我们定义一个匿名方法,并允许我们以函数式接口的方式使用它。我们也希望能够在已有的方法上实现同样的特性。
方法引用和lambda表达式拥有相同的特性(例如,它们都需要一个目标类型,并需要被转化为函数式接口的实例),不过我们并不需要为方法引用提供方法体,我们可以直接通过方法名称引用已有方法。
以下面的代码为例,假设我们要按照name或age为Person数组进行排序:
class Person {
private final String name;
private final int age;
public int getAge() { return age; }
public String getName() {return name; }
...
}
Person[] people = ...
Comparator<Person> byName = Comparator.comparing(p -> p.getName());
Arrays.sort(people, byName);
在这里我们可以用方法引用代替lambda表达式:
Comparator<Person> byName = Comparator.comparing(Person::getName);
这里的Person::getName可以被看作为lambda表达式的简写形式。尽管方法引用不一定(比如在这个例子里)会把语法变的更紧凑,但它拥有更明确的语义——如果我们想要调用的方法拥有一个名字,我们就可以通过它的名字直接调用它。
因为函数式接口的方法参数对应于隐式方法调用时的参数,所以被引用方法签名可以通过放宽类型,装箱以及组织到参数数组中的方式对其参数进行操作,
就像在调用实际方法一样:
Consumer<Integer> b1 = System::exit; // void exit(int status)
Consumer<String[]> b2 = Arrays:sort; // void sort(Object[] a)
Consumer<String> b3 = MyProgram::main; // void main(String... args)
Runnable r = Myprogram::mapToInt // void main(String... args)
方法引用的种类(Kinds of method references)
方法引用有很多种,它们的语法如下:
- 静态方法引用:ClassName::methodName
- 实例上的实例方法引用:instanceReference::methodName
- 超类上的实例方法引用:super::methodName
- 类型上的实例方法引用:ClassName::methodName
- 构造方法引用:Class::new
- 数组构造方法引用:TypeName[]::new
对于静态方法引用,我们需要在类名和方法名之间加入::分隔符,例如Integer::sum。
对于具体对象上的实例方法引用,我们则需要在对象名和方法名之间加入分隔符:
Set<String> knownNames = ...
Predicate<String> isKnown = knownNames::contains;
这里的隐式lambda表达式(也就是实例方法引用)会从knownNames中捕获String对象,而它的方法体则会通过Set.contains使用该String对象。
有了实例方法引用,在不同函数式接口之间进行类型转换就变的很方便:
Callable<Path> c = ...
Privileged<Path> a = c::call;
引用任意对象的实例方法则需要在实例方法名称和其所属类型名称间加上分隔符:
Function<String, String> upperfier = String::toUpperCase;
这里的隐式lambda表达式(即String::toUpperCase实例方法引用)有一个String参数,这个参数会被toUpperCase方法使用。
如果类型的实例方法是泛型的,那么我们就需要在::分隔符前提供类型参数,或者(多数情况下)利用目标类型推导出其类型。
需要注意的是,静态方法引用和类型上的实例方法引用拥有一样的语法。编译器会根据实际情况做出决定。
一般我们不需要指定方法引用中的参数类型,因为编译器往往可以推导出结果,但如果需要我们也可以显式在::分隔符之前提供参数类型信息。
和静态方法引用类似,构造方法也可以通过new关键字被直接引用:
SocketImplFactory factory = MySocketImpl::new;
- 如果类型拥有多个构造方法,那么我们就会通过目标类型的方法参数来选择最佳匹配,这里的选择过程和调用构造方法时的选择过程是一样的。
- 如果待实例化的类型是泛型的,那么我们可以在类型名称之后提供类型参数,否则编译器则会依照"菱形"构造方法调用时的方式进行推导。
数组的构造方法引用的语法则比较特殊,为了便于理解,你可以假想存在一个接收int参数的数组构造方法。
参考下面的代码:
IntFunction<int[]> arrayMaker = int[]::new;
int[] array = arrayMaker.apply(10) // 创建数组 int[10]
Java学习:方法的引用的更多相关文章
- Java学习--方法
Java学习 方法 方法 定义 Java方法是语句的集合,一起执行一个功能. 方法是解决一类问题的步骤的有序组合. 方法包含在类或对象中. 方法在程序中被创建,在其他地方被引用. 设计方法的时候,最好 ...
- Java学习——方法
在这一次的学习中我觉得首先要了解: 什么是方法呢 方法又怎么定义与调用 上面这段代码是我们经常写到的,其实它就是一个方法,其中 public 是修饰符 void是返回值类型 main就是方法名 arg ...
- Java学习之一(引用相关)
1.Java概述 首先,Java是一门面向对象的编程语言.相对于C/C++等语言,Java中没有指针,但是这不代表指针等知识不重要:Java中不存在多继承但是存在多接口.在我自己的学习过程之中,我偏向 ...
- Java学习----方法的重载
一个类中有多个同名的参数不一样的方法. 作用:可以根据不同的条件调用不同的方法. 注意:java不会因为方法的返回类型或者权限的不同而判断为不同的两个方法. public class Student ...
- Java学习---- 数组的引用传递
1. public class ArrayRefDemo01{ public static void main(String args[]){ int temp[] = {1,3,5} ; // 利用 ...
- Java学习笔记day03_引用数据类型
1.引用数据类型 步骤: 1. 导包 2. 创建引用类型变量 类型 变量名 = new 类型名(); 3. 使用数据类型的功能 变量名.功能名(); 如Scanner类: import jav ...
- Java学习----方法的覆盖
方法的覆盖:子类继承父类,子类重写父类的同名方法. 覆盖的原则: 1. 方法的参数必须跟父类保持一致 2. 子类方法的修饰符的范围必须大于等于父类方法同名的修饰符(public > privat ...
- Java学习——方法中传递参数分简单类型与复杂类型(引用类型)编程计算100+98+96+。。。+4+2+1的值,用递归方法实现
package hello; public class digui { public static void main(String[] args) { // TODO Auto-generated ...
- 0030 Java学习笔记-面向对象-垃圾回收、(强、软、弱、虚)引用
垃圾回收特点 垃圾:程序运行过程中,会为对象.数组等分配内存,运行过程中或结束后,这些对象可能就没用了,没有变量再指向它们,这时候,它们就成了垃圾,等着垃圾回收程序的回收再利用 Java的垃圾回收机制 ...
随机推荐
- 微信小程序使用函数防抖解决重复点击消耗性能问题
wxml: <view bindtap="doubleTap" bindtouchstart="touchStart" bindtouchend=&quo ...
- 四.Windows基础
系统目录 Windows Program files 用户 Perflogs:是Windows7的日志信息,如磁盘扫描错误信息,删掉可以,但不建议删,删掉反而降低系统速度,perflogs是系统自动生 ...
- 英语AquilariaCrassna奇楠沉香
越南奇楠沉香Aquilaria crassna是瑞香科沉香属植物. 奇楠香被喻为沉香中的钻石,其与身俱来的香气,淡雅宜人,汇集天地阴阳五行之气,而成为唯一能通三界之香品.长久以来,它被视为一种珍贵罕有 ...
- 将流数据输出到Mysql中
outputMysqlApp.scala import java.sql.DriverManager import org.apache.spark.SparkConf import org.apac ...
- 用Random产生1到10之间的一个随机数
bat中怎样用Random产生1到10之间的一个随机数? 当然是用%random%,示例: @echo off rem 用Random产生1到10之间的一个随机数 set num=%random% s ...
- python 之serial、pyusb 使用开发
说明:本次是在windows 系统操作实现的. serial 使用场景,获取得力扫码枪的扫码数据,该扫码枪支持三种通讯接口设置,如下图 即插即用的是 USB-KBW功能,插上去即可获取扫码数据,第二种 ...
- docker研究-5 docker网络介绍
例子:启动(创建)一个容器,自定义容器名字为my_nginxtest02,镜像为nginx,将宿主机(本机)81端口映射到容器的80端口 [root@localhost ~]# docker run ...
- Python语言基础01-初识Python
本文收录在Python从入门到精通系列文章系列 1. Python简介 1.1 Python的历史 Python的创始人为吉多·范罗苏姆(荷兰语:Guido van Rossum) 1989年的圣诞节 ...
- 201871010124-王生涛《面向对象程序设计(java)》第十四周学习总结
项目 内容 这个作业属于哪个课程 <任课教师博客主页链接>https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 <作业链接地址>http ...
- 第十二周博客作业 <西北师范大学| 周安伟>
第十二周作业 助教博客链接https://home.cnblogs.com/u/zaw-315/ 作业要求链接https://www.cnblogs.com/nwnu-daizh/p/10831971 ...