话不多说,先看看下面代码,
上图中java定义个一个回调接口ActionListener,通过该接口来指定监听之后按钮的行为并添加相应操作。先看图一咯,一般我们监听一个按钮是用匿名内部类的形式,而不会专门去创建一个implement ActionListener的类,但是,这样的代码也有很多看着不爽,用着也不爽的地方,比如语法过于冗余、匿名内部类的this和demo类的this让人难以理解、类型载入和实例创建语义不够灵活的局部变量等,所以呢,java8针对这些做了相应的改变,那就是图二的写法,也就是名叫lambda的写法,是不是看上去就简单明了多了咯,要掌握lambda的用法,那先得知道functional interfaces的概念和定义。
函数式接口的定义是很easy的,怎么说呢?我们定义一个接口,接口中只有一个abstract方法,那么此接口就是函数式接口,除了一个abstract方法,就不能定义其他method了嘛,怎么可能嘛,我们还可以根据自己的需求定义default method、static method,但是要注意一个点,比如Comparator ,首先可以肯定的是它是一个函数式接口,但是你看它的源码,它定义了equals和compare两个抽象方法。所以说除object定义过的方法,如equals、toString还有其他的default、static 方法这些都不属于函数式接口的范畴。为了更好的定义一个函数式接口,可以用注解@FunctionalInterface 显式的告诉编译器它是一个函数式接口。
在java7中阿,有一些函数式接口,比如Runable、Callable、PrivilegedAction、Comparator、FileFilter等,除了这些之外,java 8为我们提供了很多常用的函数式接口,在java.util.function包下。简单晓得了函数式接口的概念和定义,然后怎么用了,顾名思义肯定是和lambda一起用咯!
看两个简单lambda表达式
语法: (参数列表) -> {表达式}
表达式:表达式会被执行然后返回执行结果。
语句块:语句块中的语句会被依次执行,就像方法中的语句一样——
return 语句会把控制权交给匿名方法的调用者
break 和 continue 只能在循环中使用
如果函数体有返回值,那么函数体内部的每一条路径都必须返回值
简单说明一哈,当参数为空时或参数数量在两个或两个以上时,参数列表的()不能省,当表达式只有一条语句时可以省大括号。
目标类型
有一个小问题哦,函数式接口的名称并不是 lambda 表达式的一部分,那么lambda表达式的类型是什么呢?例:第一个小例子来的,下图中的lambda表达式的目标类型是ActionListener,
所以这是怎么知道此lambda表达式的目标类型是ActionListener,其实是编译器根据lambda表达式的上下文推导的,被推导出来的这个类型就叫做目标类型,当然,lambda 表达式对目标类型也是有要求的。编译器会检查 lambda 表达式的类型和目标类型的method signature是否一致。当且仅当下面所有条件均满足时,lambda 表达式才可以被赋给目标类型 T:
方法引用
方法引用和 lambda 表达式拥有相同的特性(例如,它们都需要一个目标类型,并需要被转化为函数式接口的实例),不过我们并不需要为方法引用提供方法体,我们可以直接通过方法名称引用已有方法。
看一个例子吧!
这里的话我们就可以用方法引用代替这个lambda表达式,其实方法引用就类似于lambda表达式的一个简写。
方法引用有很多种,它们的语法如下:
不多说了,像lambda表达式这一类型的知识点,一定要多用拉,不然光理论,不实践的话,个人感觉屁用没有啦!个人观点,不喜勿喷啦!