摘要:方法引用在之前只能进行值传递,方法是不能传递的。首先方法接受了一个类型的对象,方法是获取所有的文件,是用来存储筛选之后的元素,循环所有获得到的文件数组,然后调用中的方法来进行条件筛选,放入后返回。
方法引用:
在Java 8之前只能进行值传递,方法是不能传递的。如果你想调用一个方法你必须先获取到它所在的类的实例,然后再通过实例去调用这个方法,但是Java 8新增了方法引用这个新特性可以让你直接把方法当做值来传递。
1.下面这段代码代码的作用是遍历获取目录下所有的文件和目录,并且还加了一个筛选条件,只筛选出不隐藏的文件和目录,这里我们其实只是想调用FileFilte中的accept方法来进行筛选,但是我们需要先创建FileFilter的匿名对象,然后重写整个accept方法,这样我们才调用到了这个方法,其中只有第三行代码是会有变化的,其他的代码都是固定的,但是我们每次还是要把其他固定的模板代码重新写一遍。
File[] hiddenFiles = new File("F: est").listFiles(new FileFilter() { public boolean accept(File file) { return !file.isHidden(); } });
2.现在Java 8中的方法引用就解决了这个问题,让我们看下列的代码,我们发现匿名类和重写方法的步骤都已经没有了,上述代码的本质其实就是调用传进来的File对象的isHidden方法,现在File:: isHiden这个写法就是和上面的代码是同样的作用,但是代码精简了很多,那些无用的冗余代码都不见了。
File[] hiddenFiles = new File("F: est").listFiles(File::isHidden);
3.我们从源码来看看listFiles方法做了什么操作,而这两种写法又有什么不同。
首先listFiles方法接受了一个FileFilter类型的对象,list方法是获取所有的文件,files是用来存储筛选之后的元素,循环所有获得到的文件数组,然后调用FileFilter中的accept方法来进行条件筛选,放入files后返回。
public File[] listFiles(FileFilter filter) { String ss[] = list(); if (ss == null) return null; ArrayListfiles = new ArrayList<>(); for (String s : ss) { File f = new File(s, this); if ((filter == null) || filter.accept(f)) files.add(f); } return files.toArray(new File[files.size()]); }
再看看FileFilter对象是什么,发现它是一个接口,所以Java 8之前的写法都是写了个匿名对象来实现这个接口,重写它的accept方法。看到这里其实很明显了,这就是一个策略模式的应用。而方法引用就是让我们直接把需要在accept方法里调用的方法传递进去,不需要像以前一样来个全家桶写一堆固定模板。
@FunctionalInterface public interface FileFilter { boolean accept(File pathname); }
4.下面的图介绍了Java 8之前和之后这段代码的逻辑流程,在Java 8之前是需要先创建FileFilter匿名对象然后再调用File.listFiles方法,而现在只需要File::isHiden写法就可以达到同样的目的,其实它的含义就是创建了一个方法引用,所以你可以通过传递引用来传递这个方法,就好像你new了一个对象的引用,然后你把这个引用传递到别的地方,你就可以调用这个对象里的属性和方法是一样的道理。
Lambda-匿名函数:上面的方法引用让我们可以把方法也当做值来进行传递,但是有时候我们传递进去的代码并没有像File.isHidden方法一样封装起来,而这种情况也是经常发生的,有时候为了一个特殊需求我需要写段代码来解决,但是次数用的极少,没必要封装个方法,而Lambda表达式则解决了这个问题。
1.比如我们想要筛选出一个文件名叫abc.txt的文件,我们可以这样写,我们看到 file.getName(). equals("abc.txt"));是我们自己写出来的,我们并没有把它封装成方法就拿来使用了,注意看->符号前面,那个代表的是上面accept方法接受的参数,而->后面则是我们拿传递进来的参数来操作,只是要确保你的这行代码返回的类型是要和accept方法的返回类型一致。
File[] files3 = new File("F: est").listFiles((File file) -> file.getName().equals("abc.txt"));
2.以上只是Lambda表达式最简单的方式,我们还可以有下列这些更加多样化的操作,Lambda表达式在Java 8中是非常重要的部分,因为后面我们讲到的stream(流)就是基于它来使用的。
//单个参数的时候可以省略括号和类型,直接写形参 File[] files4= new File("F: est").listFiles((file -> file.getName().equals("abc.txt"))); //如果要写多行代码,可以加大括号把所有代码括起来,最后你同样需要返回正确的类型 File[] files5= new File("F: est").listFiles( (File file) -> { boolean flag = file.getName().equals("d") && file.getName().contains("d"); return flag; } );
下面我会增加一篇文章关于Lambda表达式的实际应用,好让大家更好的理解它们的用法。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/71433.html
摘要:欧阳思海继承接口后,又加了新的抽象方法,这个接口就不再是函数式接口默认方法在接口中添加了一个默认方法。总结在这篇文章中,我们讲了表达式方法引用函数式接口接口中的静态方法接口中的默认方法的使用。 今天我来聊聊 Java8 的一些新的特性,确实 Java8 的新特性的出现,给开发者带来了非常大的便利,可能刚刚开始的时候会有点不习惯的这种写法,但是,当你真正的熟悉了之后,你一定会爱上这些新的...
摘要:概述简介若体中的功能,已经有方法提供了实现,可以使用方法引用可以将方法引用理解为表达式的另外一种表现形式方法引用的三种形式对象的引用实例方法名类名静态方法名类名实例方法名注意方法引用所引用的方法的参数列表与返回值类型,需要与函数式接口中抽象 1. 概述 1.1 简介 若 Lambda 体中的功能,已经有方法提供了实现,可以使用方法引用(可以将方法引用理解为 Lambda 表达式的另外一...
摘要:实际上方法引用是表达式的一种语法糖。小结本篇全面介绍了方法引用的四种使用方式,且每种方式都有对应一个示例来帮助大家理解。 上一篇我们详细介绍了Optional类用来避免空指针问题,本篇我们全面了解一下Java8中的方法引用特性。方法引用是lambda表达式的一种特殊形式,如果正好有某个方法满足一个lambda表达式的形式,那就可以将这个lambda表达式用方法引用的方式表示,但是如果这...
摘要:大家好,我是乐字节的小乐,上一次我们说到了核心特性之函数式接口,接下来我们继续了解又一核心特性方法引用。方法引用是一种更简洁易懂的表达式。感谢光临阅读小乐的,敬请关注乐字节后续将继续讲述等前沿知识技术。 大家好,我是乐字节的小乐,上一次我们说到了Java8核心特性之函数式接口,接下来我们继续了解Java8又一核心特性——方法引用。 showImg(https://segmentfaul...
摘要:表达式简介表达式是一个匿名函数对于而言并不很准确,但这里我们不纠结这个问题。如果表达式的正文有一条以上的语句必须包含在大括号代码块中,且表达式的返回值类型要与匿名函数的返回类型相同。 版权声明:本文由吴仙杰创作整理,转载请注明出处:https://segmentfault.com/a/1190000009186509 1. 引言 在 Java 8 以前,若我们想要把某些功能传递给某些方...
阅读 3857·2023-04-26 00:36
阅读 2667·2021-11-16 11:44
阅读 1082·2021-11-15 17:58
阅读 1665·2021-09-30 09:47
阅读 1208·2019-08-30 13:05
阅读 1538·2019-08-30 12:55
阅读 2408·2019-08-30 11:02
阅读 2715·2019-08-29 17:01