方法引用通过方法的名字来指向一个方法。
方法引用可以使语言的构造更紧凑简洁,减少冗余代码。
方法引用使用一对冒号 :: 。
下面,我们在 Car 类中定义了 4 个方法作为例子来区分 Java 中 4 种不同方法的引用。

方法引用实际上是某些 Lambda 表达式的更简洁写法,原因就是在这些情况下,编译器能够智能的推断出参数体中的值究竟是方法的传入参数还是调用者

方法引用有以下四种形式:

类型 示例
构造方法引用 ClassName::new
静态方法引用 ClassName::staticMethodName
特定类的任意对象的方法引用 ClassName::methodName
特定对象的实例方法引用 instance::methodName

上面的四种形式的实例:

Supplier.java

package java.util.function;

@FunctionalInterface
public interface Supplier<T> {
T get();
}

Car.java

package com.boomoom;

import java.util.function.Supplier;

public class Car {
//Supplier是jdk1.8的接口,这里和lambda一起使用了
public static Car create(final Supplier<Car> supplier) {
return supplier.get();
} public static void collide(final Car car) {
System.out.println("Collided " + car.toString() + " and it went boom!");
} public void follow(final Car another) {
System.out.println("Following the " + another.toString());
} public void repair() {
System.out.println("Repaired " + this.toString());
}
}

Maintest.java

package com.boomoom;

import java.util.Arrays;
import java.util.List; public class MainTest {
public static void main(String[] args) { // 构造器引用:它的语法是Class::new,或者更一般的Class<T>::new实例如下:
Car[] carList = new Car[2];
final Car car0 = Car.create(Car::new);
carList[0] = car0;
final Car car1 = Car.create(Car::new);
carList[1] = car1;
final List< Car > cars = Arrays.asList( carList ); // 静态方法引用:它的语法是Class::static_method,实例如下:
cars.forEach( Car::collide ); // 特定类的任意对象的方法引用:它的语法是Class::method实例如下:
cars.forEach( Car::repair ); // 特定对象的方法引用:它的语法是instance::method实例如下:
final Car police = Car.create( Car::new );
cars.forEach( police::follow );
}
}

构造方法引用

根据 Supplier 接口的定义,其为函数式接口,我们调用静态方法 create 创建 Car 对象的时候,代码应该是如下所示的:

 Car.create(new Supplier<Car>() {
@Override
public Car get() {
return new Car();
}
});

用 Lambda 表达式,更简单的写法就是:

 Car.create(()->new Car());

可以看到,Car 类存在一个不带参数的构造方法,所以编译器不需要根据参数列表猜测构造方法的参数(因为都是空的),所以就有一个更加简单的写法:

 Car.create(Car::new);

实际上,如果 Lambda 的参数个数和类的构造方法个数一致,也可以改写为上面的形式,只要是没有歧义即可。

静态方法引用

我们创建一个 Car 对象,接着将其添加进一个 List 中:

 final Car car = Car.create(Car::new);
final List<Car> cars = Arrays.asList(car);

Java8 中给 Iterable 接口添加了 forEach 方法方便我们遍历集合类型。

现在假设我们要给 List 中的每个 Car 对象调用一次 Car.collide(Car car) 静态方法,那么可以使用 forEach 方法,而 forEach 方法需要传入一个 Consumer,恰好,这个 Consumer接口也带有 FunctionalInterface 注解,所以我们一步一步的来看:

 cars.forEach(new Consumer<Car>() {
@Override
public void accept(Car car) {
Car.collide(car);
}
});

写成 Lambda:

 cars.forEach(c -> Car.collide(c));

就是对传进来的 Car 对象执行静态方法,很简单。但是实际上,对于静态方法,编译器也不需要推断调用者(类名),当传入参数和静态方法所需参数个数一致时,就不存在歧义:

所以这里可以直接使用方法引用:

 cars.forEach(Car::collide);

类成员方法引用

类的成员方法不能是静态的,而这个情况其实和静态方法类似,区别是,Lambda 表达式的参数个数需要等于所调用方法的入参个数加一。

为什么要加一?

因为类的成员方法不能通过类名直接调用,只能通过对象来调用,也就是Lambda表达式的第一个参数,是方法的调用者,从第二个开始的参数个数要和需要调用方法的入参个数一致即可。如下图所示:

对于上面的例子,如果要对List中的每个对象执行一次它的repair方法:

 cars.forEach(c -> c.repair());

根据上图,这里参数只有一个,而 repair 方法没有入参,所以不存在歧义,即可以改写为对应的方法引用:

 cars.forEach(Car::repair);

对象方法引用

与类方法引用不同的是,对象方法引用方法的调用者是一个外部的对象。如下图:

对于上面例子,可以再创建一个 Car 的对象 police,并让 police 调用 follow 方法跟踪 List 中的每个 Car:

 final Car police = Car.create(Car::new);
cars.forEach((car1) -> police.follow(car1));

改成对象方法引用:

 cars.forEach(police::follow);

至此,方法引用也完成了。

参考:https://www.cnblogs.com/Fndroid/p/6087380.html

http://www.runoob.com/java/java8-method-references.html

http://www.cnblogs.com/xiaoxi/p/7099667.html

Java 8 特性 —— 方法引用的更多相关文章

  1. JAVA8新特性——方法引用

    JAVA9都要出来了,JAVA8新特性都没搞清楚,是不是有点掉队哦~ 在Lamda新特性的支持下,JAVA8中可以使用lamda表达式来创建匿名方法.然而,有时候我们仅仅是需要调用一个已存在的方法(如 ...

  2. 【Java 8】方法引用

    一.概述 在学习lambda表达式之后,我们通常使用lambda表达式来创建匿名方法.然而,有时候我们仅仅是调用了一个已存在的方法.如下: Arrays.sort(stringsArray,(s1,s ...

  3. java中的方法引用(method reference)官方文档总结

    2017/7/5 转载写明出处:http://www.cnblogs.com/daren-lin/p/java-method-reference.html 今天要说的是java中的一项新特性,方法引用 ...

  4. java中的方法引用

    引用静态方法:类名称::static 方法名称: 引用某个对象的方法:对象::普通方法: 引用特定类方法:特定类::方法 引用构造方法:类名称::new 范例:引用静态方法 package com.j ...

  5. Java学习笔记-方法引用

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

  6. Java 8Lambda之方法引用(Method References)

    方法引用分为4类,方法引用也受到访问控制权限的限制,可以通过在引用位置是否能够调用被引用方法来判断.具体分类信息如下: 类型 使用方式 静态方法 ContainingClass::staticMeth ...

  7. Java自学-Lambda 方法引用

    Lambda 方法引用 步骤 1 : 引用静态方法 首先为TestLambda添加一个静态方法: public static boolean testHero(Hero h) { return h.h ...

  8. Java基础教程——方法引用

    方法引用 Lambda表达式的代码,是否可以再简洁?--方法引用 对象/类名::方法名 参数都不用写明. import java.util.function.Consumer; public clas ...

  9. java8新特性——方法引用与构造器引用

    上篇文章简单学习了java8内置得4大核心函数式接口,这类接口可以解决我们遇到得大多数得业务场景得问题.今天来简单学习一下方法引用与构造器引用. 一.方法引用 方法引用:若lambda 体中得内容已经 ...

随机推荐

  1. 学JAVA第十三天,方法、方法重载及构造函数

    今天终于不讲狗跳楼的问题了,今天讲了方法,方法重载及构造函数及构造函数重载的课程了. 这里说了有参好无参的,下面讲构造函数重载和方法重载. 其实,这上面写的这些方法,就相当一个模板.想要快速做出产品就 ...

  2. glibc溢出提权CVE-2018-1000001总结

    遇到了好几个centos6.5,一直尝试想提权.暂未成功,靶机内核:2.6.32-696.18.7.el6.x86_64. glibc版本:ldd (GNU libc) 2.12 目前编译过程中都发现 ...

  3. eclipse导入java工程

    1)File下的import选项 2)点击General,选择Existing Projects into Workspace,点击next 3)点击Browse,在弹出的窗口中选择导入工程所在的文件 ...

  4. 基于html5 plus + Mui 移动App开发(一)

    使用Html5 plus + Mui 进行移动App开发,有一段时间了,这几日得空,做个资讯App分享给大家. 今天主要分享主页实现,首先看下效果: 此界面主要分为:标题.内容分类列表.搜索及设置按钮 ...

  5. 用Gogs在Windows上搭建Git服务

    1.下载并安装Git,如有需求,请重启服务器让Path中的环境变量生效. 2.下载并安装Gogs,请注意,在Windows中部署时,请下载MiniWinService(mws)版本. 3.在Maria ...

  6. 【English】四、Y结尾名词变复数

    一.辅音字母+y结尾的名词,将y改变为i,再加-es. 读音变化:加读[z]. 例: candy→candies; daisy→daisies; fairy→fairies; lady→ladies; ...

  7. 阿里云服务器,Sql Server 本地连接服务器端问题记录

    1.如果你是阿里云服务器,配置参数都整好了并且排除了防火墙问题(关闭了防火墙),依然没有连接上,那就先考虑这个问题 问题:阿里云服务器的SQLServer不允许远程连接 原因:因为除了服务器上的防火墙 ...

  8. 用Jenkins搭建自动构建服务

    Jenkins是BS跨平台构建工具,之前名为Hundson.wiki [chs  en]  最新windows安装包:下载 下文以1.593版本为例,讲述Jenkins的Windows版本的一些要注意 ...

  9. SQL ----post漏洞测试注入

    使用工具sqlmap 输入账号密码进行bp截断,获取文本保存在sqlmap下面2.txt 爆数据库 爆表爆表 爆数据 最后把数据密码md5解析

  10. Redmine入门-安装

    Redmine提供了两种方式安装,如果仅仅只是使用Redmine,建议采用一键安装的方式,快捷方便.如果需要做二次开发或者更多的个性化处理,可以采用源码安装方式,下面分别介绍两种安装方式. ----- ...