Java泛型

1. 泛型入门

1.1 泛型 Generic Programming

  • 泛型类:ArrayList, HashSet, HashMap等
  • 泛型方法:Collections.binarySearch,Arrays.sort等
  • 泛型接口:List, Iterator等

1.2 泛型的本质:参数化类型,避免类型转换,代码可复用

2. 自定义泛型

2.1 泛型类

  • 具有泛型变量的类
  • 在类名后用代表引入类型
  • 多个字母表示多个引入类型,如<T,U>等
  • 引入类型可以修饰成员变量/局部变量/参数/返回值
  • 没有专门的template关键字

2.2 泛型方法

  • 具有泛型参数的方法
  • 该方法可以在普通类/泛型类中
  • 在修饰符后,返回类型前
public class ArrayUtil {
  public static <T> T getMiddle(T... a) {}
}
String s = ArrayUtil.<String>getMiddle("abc", "def");

2.3 泛型接口

  • 和泛型类相似,在类名后加
  • T用来指定方法返回值和参数
  • T也可以再是一个泛型类
  • 实现接口时,指定类型

2.4 总结

  • 泛型类:整个类都被泛化,包括变量和方法
  • 泛型方法:方法都被泛化,包括返回值和参数
  • 泛型接口:泛化子类方法

3. 泛型类型限定

3.1 泛型限定

  • 约定T必须是Comparable的子类
  • extends固定,后面可以多个,以&拼接,可以有多个接口,但只能一个类,且类必须排第一位
  • 逗号分隔参数

3.2 泛型类之间的继承

  • Pair<S>Pair<T>没有任何关系,无论S和T之间是什么关系
  • 泛型类可以扩展或实现其他的类,如ArrayList<T>实现List<T>

3.3 界定符

  • Pair<? extends S>
    Pair能接收的参数类型,是S自身或子类
    只能get,不能set,只生产,不消费,编译器只能保证出来的类型,但不能保证放入的对象是声明类型

  • Pair<? super S>
    Pair能接收的参数类型,是S自身或超类
    只能set,不能get,只消费,不生产,编译器保证放入的是S自身或超类,但不能保证出来的是什么具体类型

  • PECS原则,Producer Extends, Consumer Super

3.4 无限定符的泛型

  • Pair<T>,原始类型
  • Pair<?>,无限定通配符,表示任意类型,获取元素只能赋值给Object,无法放入任何对象,甚至是Object

4. 泛型的本质

4.1 类型擦除

  • 虚拟机中没有泛型,只有普通类和方法
  • 在编译阶段,泛型参数被擦除为第一个限定类型,如无限定类型,擦除为Object
  • 重载泛型方法翻译(自动桥方法)保持方法多态
  • 静态变量不支持泛型。

5. Java类型协变和逆变

5.1 定义

5.2 详情

  • Java数组是协变的
    String是Object子类,String[]是Object[]的子类

  • Java的(原始)泛型是不变的
    String是Object子类,List和List没有关系

  • 复合情况
    数组协变,泛型不变

  • 支持协变

    ArrayList<? extends A> list = new ArrayList<B>();

  • 支持逆变

    ArrayList<? super B> list = new ArrayList<A>();

posted @ 2022-06-28 00:08  hunter-w  阅读(35)  评论(0编辑  收藏  举报