文字欲程序员

对Lambda的一些感悟---基础

2019-02-18  本文已影响8人  绍圣

Java8已经发布很久了,作为一个使用者,发现自己居然都没有正式的去研究过Java8中最重要的改变--Lambda。Lambda表达式是一种新语法,至此Java开始开启函数式编程的大门。

前言

Java都是把实物封装成对象,一切皆是对象。但是缺少功能性对象(功能函数:把代码块当做对象(数据))。即代码=对象。以前的做法可以使用内部类,其中匿名内部类可以在类的内部不需要特别命名而去实现一个类。但是这样写出的代码可读性比较差。

Lambda

函数式接口:只拥有一个方法的接口。Runnable接口、Callable<T>接口、Comparator<T>接口等大多数的回调接口都是函数式接口。我们可以通过@FunctionalInterface注解显示指定一个接口为函数式接口,加上这个注解后,编译器会验证该接口是否满足函数式接口的要求。Lambda表达式的类型就是对应函数接口的类型。

语法:lambda表达式的语法由参数列表,箭头符号(->)和函数体组成。函数体既可以是一个表达式,也可以是一个语句块。

1,表达式:会被执行然后返回执行结果。

2,语句块:语句块中的语句被依次执行。

如果函数体有返回值,那么函数体内部的每一条路径都必须返回值。

目标类型:函数式接口的名称不是lambda表达式的一部分,那么一个lambda表达式的类型是什么喃?类型由上下文推导而来。同样的lambda表达式在不同上下文里可以拥有不同的类型。编译器负责推导lambda表达式类型。

lambda表达式只能出现在目标类型为函数式接口的上下文中。

当满足以下条件,lambda表达式才可以被赋给目标类型T:

1,T是一个函数式接口。

2,lambda表达式的参数和T的方法参数在数量和类型上一一对应。

3,lambda表达式的返回值和T的方法返回值相兼容。

4,lambda表达式内所抛出的异常和T的方法throws类型相兼容。

词法作用域:lambda不会从超类中继承任何变量名,不会引入一个新的作用域。lambda表达式函数体里面的变量和它外面环境的变量具有相同的语义。lambda表达式不可以掩盖任何其所在上下文的局部变量。

变量捕获:在java8中对于lambda表达式和内部类,允许获取有效只读的变量。有效只读:一个局部变量在初始化后从未被修改过,就符合有效只读的要求。lambda表达式不支持修改捕获的变量。

如果lambda表达式没有捕获外部类的成员就不会保留对外部类实例的引用。

方法引用:直接通过方法名称引用已有方法。

1,静态方法引用:ClassName::methodName。

2,实例上的实例方法引用:instanceReference::methodName。

3,超类上的实例方法引用:super::methodName。

4,类型上的实例方法引用:ClassName::methodName。

5,构造方法引用:Class::new。

6,数组构造方法引用:TypeName[]::new。

默认方法:在以前接口在发布后就已经被定型了,除非我们能够一次性更新所有该接口的实现,否则向接口添加方法就会破坏现有的接口实现。默认方法的出现解决了这个问题,使得接口在发布之后仍然可以继续演变。

默认方法为接口添加新的行为,这样接口方法可以是抽象的或者是默认的。默认方法拥有默认的实现,实现接口的类型通过继承得到该默认实现,默认方法不是抽象方法,所以我们可以放心的向函数式接口里增加默认方法,而不用担心函数式接口的单抽象方法限制。

当接口继承其它接口时,我们既可以为它所继承而来的抽象方法提供一个默认实现,也可以为它继承而来的默认方法提供一个新的实现,还可以把它继承而来的默认方法重新抽象化。

静态接口方法:java8允许在接口中定义静态方法。

参考:

深入理解Java 8 Lambda(语言篇——lambda,方法引用,目标类型和默认方法) | lucida

深入理解Java 8 Lambda(类库篇——Streams API,Collectors和并行)

上一篇下一篇

猜你喜欢

热点阅读