Java 8 的泛型增强

Java 5 引入了泛型,这是一次重大的改进,从此集合中的东西不需要每次显式的去转型。不过 Java 5 还不具备类型推断的能力,所以声明泛型必须写成

List<String> list = new ArrayList<String>();

一直到 Java 6 也是如此。自 Java 7 起泛型增强为可根据声明类型进行推断,所以 Java 7 中可以这么写

List<String> list = new ArrayList<>();  //<> 中的参数可省略,如果类型参数多, 或多层嵌套时很省事

List<String> list = Collections.emptyList(); //见  Java 泛型 -- 依据声明的变量类型自动推断

Java 8 开始对泛型类型推断又进一步增强:可根据方法上下文进行推断,例如下面的代码在 Java 7 下编译不过

报编译错误:

Test.java:10: error: no suitable method found for addAll(ArrayList<Object>)
    list.addAll(new ArrayList<>());
        ^
    method List.addAll(int,Collection<? extends Integer>) is not applicable
      (actual and formal argument lists differ in length)
    method List.addAll(Collection<? extends Integer>) is not applicable
      (actual argument ArrayList<Object> cannot be converted to Collection<? extends Integer> by method invocation conversion)
    method Collection.addAll(Collection<? extends Integer>) is not applicable
      (actual argument ArrayList<Object> cannot be converted to Collection<? extends Integer> by method invocation conversion)
1 error

也就 addAll() 的参数 new ArrayList<>() 无法推断出类型,被假定类型为默认的 Object, 所以无法把 ArrayList<Object> 加到 List<String> 中去。

但是用 Java 8 编译上面的代码是没问题的,也就是 Java 8 在编译 list.addAll(new ArrayList<>()) 推断为 list.addAll(new ArrayList<String>()),即通过方法参数上下文推断出实际创建的类型。

上面的代码有还一种很怪异的写法

不过不管是 Java 7 还是 Java 8 编译这段代码都会有警告

Note: Test.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.

就像是写成 List<String> list = new ArrayList() 省略了 <> 一样的编译警告。但基本可以保证我们没有机会搞出 new <String>ArrayList() 这种玩法。

最后一句,其实可别忽视了 Java 8 对类型推断的增强,它的主要工作重点是在如何根据上下文, 把一个 Lambda 表达式经由 SAM 的映射关系, 推断出对就的对象类型来。

本文链接 https://yanbin.blog/java-8-generic-enhance/, 来自 隔叶黄莺 Yanbin Blog

[版权声明] Creative Commons License 本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。

Subscribe
Notify of
guest

1 Comment
Inline Feedbacks
View all comments
chenhua
chenhua
6 years ago

Nice work.