美文网首页
深入理解Java泛型

深入理解Java泛型

作者: 俊杰的笔记 | 来源:发表于2017-05-18 11:49 被阅读189次

Java类型系统

参考:http://www.infoq.com/cn/articles/cf-java-generics

在Java中,大家比较熟悉的是通过继承机制而产生的类型体系结构。比如String继承自Object。根据Liskov替换原则,子类是可以替换父类的。当需要Object类的引用的时候,如果传入一个String对象是没有任何问题的。但是反过来的话,即用父类的引用替换子类引用的时候,就需要进行强制类型转换。编译器并不能保证运行时刻这种转换一定是合法的。这种自动的子类替换父类的类型转换机制,对于数组也是适用的。 String[]可以替换Object[]。但是泛型的引入,对于这个类型系统产生了一定的影响。正如前面提到的List<String>是不能替换掉List<Object>的。
引入泛型之后的类型系统增加了两个维度:一个是类型参数自身的继承体系结构,另外一个是泛型类或接口自身的继承体系结构。第一个指的是对于 List<String>和List<Object>这样的情况,类型参数String是继承自Object的。而第二种指的是 List接口继承自Collection接口。对于这个类型系统,有如下的一些规则:
相同类型参数的泛型类的关系取决于泛型类自身的继承体系结构。即List<String>是Collection<String> 的子类型,List<String>可以替换Collection<String>。这种情况也适用于带有上下界的类型声明。
当泛型类的类型声明中使用了通配符的时候, 其子类型可以在两个维度上分别展开。如对Collection<? extends Number>来说,其子类型可以在Collection这个维度上展开,即List<? extends Number>和Set<? extends Number>等;也可以在Number这个层次上展开,即Collection<Double>和 Collection<Integer>等。如此循环下去,ArrayList<Long>和 HashSet<Double>等也都算是Collection<? extends Number>的子类型。
如果泛型类中包含多个类型参数,则对于每个类型参数分别应用上面的规则。

总结:
使用了泛型参数的类叫泛型类,下面简称“类”和“泛型参数”。

  1. 当泛型参数相同时, 按类的继承体系。如List<String>是Collection<String>的子类。
  2. 泛型参数无通配符时,看做不可变的泛型参数。即使类相同,也无任何继承关系。如:List<Integer>和List<Number>没有关系。
  3. 泛型参数有通配符时,参数相同时,看类的关系;类相同时,看参数的关系。都不相同时,两者都要看。如ArrayList<Long>和 HashSet<Double>等也都算是Collection<? extends Number>的子类型.

关于extends和super

假定现有A和B两个类, B是A的子类,则
List<B>是List<? extends A>的子类;
List<A>是List<? super B>的子类(注意这一条,参数和类的关系正好相反)

  • 如果一个类只需要读取,用extends
    从List<? extends T>中读取,必然可以判定元素为T类型。T t = list.get(0);
    每一个元素必然是T类型的,所以可以get并用T引用。
    但是,写入时,编译器不知道list中元素具体是哪个子类型,写入另一种子类对象 不能保证元素一致性。

  • 如果一个类只需要写入,用super;
    写入List<? super T>时,编译器可以确定写入的元素只要是T类型及其子类即可。
    但读取时,编译器不知道具体是哪个父类,只能用Object t = list.get(0);

  • 如果既要读又要写,不要用通配符。

相关文章

  • 泛型

    java 泛型详解-绝对是对泛型方法讲解最详细的,没有之一Java泛型深入理解加泛型面试数组的协变性与范型的不可变性

  • Java 泛型擦除原理

    问:请比较深入的谈谈你对 Java 泛型擦除的理解和带来的问题认识? 答:Java 的泛型是伪泛型,因为在编译期间...

  • 2018-07-16

    Java 阅读 大白话说Java泛型 深入理解Java集合框架 java构造代码块详解 Java中Overload...

  • 【Android】 Kotlin(七)泛型

    深入理解Kotlin泛型 Kotlin 的泛型与 Java 一样,都是一种语法糖,即只在源代码中有泛型定义,到了c...

  • 深入理解 Java 泛型

    [TOC] 深入理解 Java 泛型 概述 泛型的本质是参数化类型,通常用于输入参数、存储类型不确定的场景。相比于...

  • 深入理解Java泛型

    Java类型系统 参考:http://www.infoq.com/cn/articles/cf-java-gene...

  • 深入理解 Java 泛型

    ? 本文已归档到:「javacore」? 本文中的示例代码已归档到:「javacore」 1. 为什么需要泛型 J...

  • Java泛型深入理解

    泛型之前[https://www.bilibili.com/video/BV1Jt4y1r782?spm_id_f...

  • 深入理解Java泛型

    我们都知道Java泛型的实现依赖于类型擦除,但是不可能完全擦除,因为运行时还是要知道泛型的真实类型的,那这个真是类...

  • 安卓面试概要点

    Java基础 访问修饰符 √ 类加载深入理解Java类加载器ClassLoaderJava中类加载的执行顺序 泛型...

网友评论

      本文标题:深入理解Java泛型

      本文链接:https://www.haomeiwen.com/subject/djksxxtx.html