博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Lambda方法引用、构造器引用、闭包
阅读量:2442 次
发布时间:2019-05-10

本文共 3282 字,大约阅读时间需要 10 分钟。

方法引用

有时,可能已经有现成的方法可以完成我们想要传递到其他代码的某个动作,就可以使用方法引用。

package pers.zhang.syntax;import pers.zhang.interfaces.LambdaSingleReturnSingleParameter;/** * @author zhang * @date 2020/1/10 - 21:36 */public class Syntax3 {
public static void main(String[] args) {
/* 方法引用:可以快速的将一个Lambda表达式的实现指向一个已经实现的方法。 语法: 方法的隶属者::方法名 (静态方法隶属于类,普通方法隶属于对象) 注意: 1.参数数量和类型一定要和接口中定义的方法一致。 2.返回值类型一定要和接口中定义的方法一致。 */ LambdaSingleReturnSingleParameter lambda1 = a -> change(a); //方法引用:引用了change方法的实现 LambdaSingleReturnSingleParameter lambda2 = Syntax3::change; } private static int change(int a){
return a * 2; }}

从上面的例子可以看出,要用 :: 操作符 分隔方法名于对象或类名。

主要有3种情况:

  • object::instanceMethod
  • Class::staticMethod
  • Class::instanceMethod

前2种情况中,方法引用等价于提供方法参数的lambda表达式。(即System.out::pritln等价于 x -> System.out.println(x)。)

对于第三种情况,第一个参数会成为方法的目标。例如String::compareToIgnoreCasse等价于 (x, y) -> x.compareToIgnoreCase(y)。

注意:如果有多个同名的重载方法,编译器会尝试从上下文中找出你指定的那一个方法。例如,Math.max方法有两个重载,一个用于int,一个用于double。选择哪一个取决于Math::max转换为哪个函数式接口的方法参数。类似于lambda表达式,方法引用不能独立存在,总是会转换为函数式接口的实例。


可以在方法引用中使用this参数。例如,this::equals 等同于 x -> this.equals(x)。使用super也是合法的。

例如:

super::instanceMethod

使用this作为目标,会调用给定方法的超类版本。

例子

class Greeter{
public void greet() {
System.out.println("hello world!"); }}class TimedGreeter extends Greeter{
public void greet() {
Timer t = new Timer(1000, super::greet); }}

TimedGreeter.greet方法开始执行时,会构造一个Timer,它会在每次定时器滴答时执行super::greet方法。这个方法会调用超类的greet方法。

构造器引用

构造器引用与方法引用类似,只不过方法名为new。例如:Person::new是Person构造器的一个引用。

可以使用数组类型建立构造器引用。例如,int[]::new 是一个构造器引用,他有一个参数即数组的长度。这等价于lambda表达式 x -> new int[x]。

package pers.zhang.syntax;import pers.zhang.data.Person;/** * @author zhang * @date 2020/1/10 - 21:55 */public class Syntax4 {
public static void main(String[] args) {
PersonCreater creater = () -> new Person(); /* 构造方法的引用: */ PersonCreater creater1 = Person::new; Person a = creater1.getPerson(); System.out.println(a); PersonCreater2 creater2 = Person::new; Person b = creater2.getPerson("Tom", 18); System.out.println(b); }}//需求interface PersonCreater{
Person getPerson();}interface PersonCreater2{
Person getPerson(String name, int age);}

closure

从功能性上说lambda和closure(或是OC中的blocks)是一个东西,只是不同语言的不同称呼罢了,它们都是匿名函数。若匿名函数捕获了一个外部变量,那么它就是一个closure。

注意事项:

  • lambda表达式中捕获的变量必须实际上是最终变量(effectively final)。
    例如下面的做法是不合法的:线程不安全
public static void countDown(int start, int delay){
ActionListener listener = event -> {
start--;//错误!!! System.out.println(start); }; new Timer(delay, listener).start();}
  • lambda表达式中也不能有同名的局部变量
    在Lambda表达式中声明一个局部变量同名的参数或局部变量是不合法的:因为Lambda的体与嵌套块有相同的作用域。
Path first = Paths.get("/usr/bin");Comparator
comp = (first, second) -> first.length() - second.length();//错误!!first变量重复定义
  • 在一个lambda表达式中使用this关键字时,是指向创建这个lambda表达式的方法的this参数。
    示例:
public class Application(){
public void init(){
ActionListener listener = event -> {
System.out.println(this.toString()); } }}

表达式this.toString()会调用Application对象的toString()方法,而不是ActionListener实例的方法。在Lambda表达式中,thsi的使用并没有任何特殊之处。lambda表达式的作用域嵌套在init方法中,与出现在这个方法中的其他位置一样,lambda表达式中this的含义并没有变化。

转载地址:http://wupqb.baihongyu.com/

你可能感兴趣的文章
firebase vue_使用Vue和Firebase,Pt 3构建Google Keep Clone
查看>>
nl-mean程序下载_将MEAN应用程序部署到Amazon EC2(第1部分)
查看>>
使用Node.js构建实时Markdown编辑器
查看>>
wordpress 插件_如何构建WordPress插件(第2部分)
查看>>
laravel调试项目_在Laravel中调试查询
查看>>
火狐打开页面按钮类插件_在Firefox中的“最后打开”选项卡上返回“关闭”按钮...
查看>>
ChromePlus – Chromium浏览器的增强版
查看>>
在Firefox中以电影院风格观看YouTube视频
查看>>
在桌面上访问您的Google阅读器新闻提要
查看>>
使用默认程序编辑器修改基本系统设置
查看>>
趋势科技用的自动化测试工具_使用趋势科技的免费工具帮助保护您的PC
查看>>
使用Jarte获取功能强大的简化文本编辑器
查看>>
火狐浏览器最小字体_轻松将Firefox最小化到系统托盘
查看>>
火狐浏览器书签工具栏图标_在Firefox中添加垂直书签工具栏
查看>>
火狐浏览器怎么录制屏幕_轻松获取Firefox中的屏幕截图
查看>>
如何从Vista升级到Windows 7 Home Premium Edition
查看>>
ccc.exe_什么是CCC.exe,为什么运行?
查看>>
synctoy 远程同步_使用SyncToy 2.1同步计算机和驱动器之间的文件夹
查看>>
powershell快捷键_在PowerShell中使用别名添加快捷方式
查看>>
修复windows修复引导_如何在Windows 7中修复无航空透明度
查看>>