第三章(3) lambda表达式类型检查、类型推断以及局部变量

     1.类型检查

     当我们在之前第一次提到lambda表达式的时候,说它可以为函数式接口生成一个实例。然而,Lambda表达式本身并不包含它在实现哪个函数式接口的信息。为了全面了解Lambda表达式,你应该知道Lambda的实际类型是什么。

      Lambda的类型是从使用Lambda的上下文推断出来的。

       所谓上下文,举个例子,比如说lambda表达式的参数与函数式接口内方法的参数,返回值类型相互对应。

       lambda表达式需要的类型,或者说lambda实现的那个函数式接口称之为目标类型。

       比如下面这段代码,当你使用lambda的时候,它背后发生了什么。看看lambda表达式的类型检查过程。

 首先,你要找出filter方法的声明。

•第二,要求它是Predicate<Apple>(目标类型)对象的第二个正式参数。

•第三,Predicate<Apple>是一个函数式接口,定义了一个叫作test的抽象方法。

•第四,test方法描述了一个函数描述符,它可以接受一个Apple,并返回一个boolean。

•最后,filter的任何实际参数都必须匹配这个要求。

2.类型推断

       你已经见过如何利用目标类型来检查一个Lambda是否可以用于某个特定的上下文。其实,它也可以用来做一些略有不同的事:推断Lambda参数的类型。比如下面这段代码例子:

我们 知道这其中的lambda是完全没有问题的,但是我们的编译器却可以像下面这样神奇的推断出lambda表达式的参数类型,而不必我们显示的去声明:

怎么样,是不是很流弊?我们的编译器会根据上下文自动的推断出参数a的类型就是Pig

请注意,有时候显式写出类型更易读,有时候去掉它们更易读。没有什么法则说哪种更好;对于如何让代码更易读,程序员必须做出自己的选择。

3.使用局部变量

    我们看到,我们现在为止lambda都只用到了主体里的参数,但是lambda表达式也允许使用自由变量。不是参数,而是在外层作用域中定义的变量:

对于引用外部变量,你可以没有限制的引用实例变量和静态变量,但是局部变量必须声明为final,或者它实际上是final

对于上面的例子,虽然他没有被显示的声明为finl,但是num变量只被赋值了一次,也就符合了“实际上是final”的条件,但是下面这种情况是无法编译通过的,我们再次对num赋值:

猜你喜欢

转载自blog.csdn.net/qq564425/article/details/81352478