Java 8函数式编程2.5 类型推断_Java 8函数式编程2.5 类型推断试读-查字典图书网
查字典图书网
当前位置: 查字典 > 图书网 > 编程 > Java 8函数式编程 > 2.5 类型推断

Java 8函数式编程——2.5 类型推断

某些情况下,用户需要手动指明类型,建议大家根据自己或项目组的习惯,采用让代码最便于阅读的方法。有时省略类型信息可以减少干扰,更易弄清状况;而有时却需要类型信息帮助理解代码。经验证发现,一开始类型信息是有用的,但随后可以只在真正需要时才加上类型信息。下面将介绍一些简单的规则,来帮助确认是否需要手动声明参数类型。 Lambda 表达式中的类型推断,实际上是Java 7 就引入的目标类型推断的扩展。读者可能已经知道Java 7 中的菱形操作符,它可使javac 推断出泛型参数的类型。参见例2-9。 例2-9 使用菱形操作符,根据变量类型做推断 Map<String, Integer> oldWordCounts = new HashMap<String, Integer>();  Map<String, Integer> diamondWordCounts = new HashMap<>();  我们为变量oldWordCounts ➊明确指定了泛型的类型,而变量diamondWordCounts ➋则使用了菱形操作符。不用明确声明泛型类型,编译器就可以自己推断出来,这就是它的神奇之处! 当然,这并不是什么魔法,根据变量diamondWordCounts ➋的类型可以推断出HashMap 的泛型类型,但用户仍需要声明变量的泛型类型。 如果将构造函数直接传递给一个方法,也可根据方法签名来推断类型。在例2-10 中,我们传入了HashMap,根据方法签名已经可以推断出泛型的类型。 例2-10 使用菱形操作符,根据方法签名做推断 useHashmap(new HashMap<>()); ... private void useHashmap(Map<String, String> values); Java 7 中程序员可省略构造函数的泛型类型,Java 8 更进一步,程序员可省略Lambda 表达式中的所有参数类型。再强调一次,这并不是魔法,javac 根据Lambda 表达式上下文信息就能推断出参数的正确类型。程序依然要经过类型检查来保证运行的安全性,但不用再显式声明类型罢了。这就是所谓的类型推断。 Java 8 中对类型推断系统的改善值得一提。上面的例子将new HashMap<>()传给useHashmap 方法,即使编译器拥有足够的信息,也无法在Java 7 中通过编译。 接下来将通过举例来详细分析类型推断。 例2-11 和例2-12 都将变量赋给一个函数接口,这样便于理解。第一个例子(例2-11)使用Lambda 表达式检测一个Integer 是否大于5。这实际上是一个Predicate——用来判断真假的函数接口。 例2-11 类型推断 Predicate<Integer> atLeast5 = x -> x > 5; Predicate 也是一个Lambda 表达式,和前文中ActionListener 不同的是,它还返回一个值。在例2-11 中,表达式x > 5 是Lambda 表达式的主体。这样的情况下,返回值就是Lambda 表达式主体的值。 例2-12 Predicate 接口的源码,接受一个对象,返回一个布尔值 public interface Predicate<T> { boolean test(T t); } 从例2-12 中可以看出,Predicate 只有一个泛型类型的参数,Integer 用于其中。Lambda表达式实现了Predicate 接口,因此它的单一参数被推断为Integer 类型。javac 还可检查Lambda 表达式的返回值是不是boolean,这正是Predicate 方法的返回类型(如图2-2)。 图2-2:Predicate 接口图示,接受一个对象,返回一个布尔值 例2-13 是一个略显复杂的函数接口:BinaryOperator。该接口接受两个参数,返回一个值,参数和值的类型均相同。实例中所用的类型是Long。 例2-13 略显复杂的类型推断 BinaryOperator<Long> addLongs = (x, y) -> x + y; 类型推断系统相当智能,但若信息不够,类型推断系统也无能为力。类型系统不会漫无边际地瞎猜,而会中止操作并报告编译错误,寻求帮助。比如,如果我们删掉例2-13 中的某些类型信息,就会得到例2-14 所示的代码。 例2-14 没有泛型,代码则通不过编译 BinaryOperator add = (x, y) -> x + y; 编译器给出的报错信息如下: Operator '& #x002B;' cannot be applied to java.lang.Object, java.lang.Object. 报错信息让人一头雾水,到底怎么回事? BinaryOperator 毕竟是一个具有泛型参数的函数接口,该类型既是参数x 和y 的类型,也是返回值的类型。上面的例子中并没有给出变量add 的任何泛型信息,给出的正是原始类型的定义。因此,编译器认为参数和返回值都是java.lang.Object 实例。 4.3 节还会讲到类型推断,但就目前来说,掌握以上类型推断的知识就已经足够了。

展开全文


推荐文章

猜你喜欢

附近的人在看

推荐阅读

拓展阅读

《Java 8函数式编程》其他试读目录

• 2.1 第一个Lambda表达式
• 2.2 如何辨别Lambda表达式
• 2.3 引用值,而不是变量
• 2.4 函数接口
• 2.5 类型推断 [当前]
• 2.6 要点回顾
• 2.7 练习
  • 大家都在看
  • 小编推荐
  • 猜你喜欢
  •