Java核心技术卷一基础知识第10版

#范型程序设计

  • 构造函数中可以省略泛型类型。
    1
    ArrayList<String> file = new ArrayList<>()
  • 出现编译错误比类在运行时出现类的强制类型转换异常要好得多。
  • 类型参数使得程序具有更好的可读性安全性
  • 泛型类可以有多个类型变量,例如 public class Pair<T, U> { ... }
  • 泛型方法可以定义在普通类中,也可以定义在泛型类中。
  • 类型变量放在修饰符的后面,返回类型的前面。
    1
    2
    3
    4
    5
    class ArrayAlg {
    public static <T> T getMiddle(T... a) {
    return a[a.length / 2];
    }
    }
  • 当调用一个泛型方法时,在方法名前的尖括号中放人具体的类型:
    1
    String middle = ArrayAlg.<String>getMiddle("John", "Q.", "Public");
  • 可以通过对类型变量 T 设置限定来对类型变量加以约束。
    1
    public static <T extends Comparable> T min(T[] a) ...
  • 一个类型变量或通配符可以有多个限定,例如:T extends Comparable & Serializable。限定类型用 & 分隔,而 , 用来分隔类型变量。
  • 在 Java 的继承中,可以根据需要拥有多个接口超类型,但限定中至多有一个类。如果用 一个类作为限定,它必须是限定列表中的第一个。[1]
  • 无论何时定义一个泛型类型,都自动提供了一个相应的原始类型(raw type)。
  • 原始类型用第一个限定的类型变量来替换,如果没有给定限定就用 Object 替换。
  • 当程序调用泛型方法时,如果擦除返回类型,编译器插入强制类型转换。
    1
    2
    3
    4
    5
    Pair<Employee> buddies = ...;
    Employee buddy = buddies.getFirst();

    // 1. 对原始方法 Pair.getFirst 的调用。
    // 2. 将返回的 Object 类型强制转换为 Employee 类型。
  • Java 泛型转换:
    • 虚拟机中没有泛型,只有普通的类和方法。
    • 所有的类型参数都用它们的限定类型替换。
    • 桥方法被合成来保持多态。
    • 为保持类型安全性,必要时插人强制类型转换。
  • 桥方法:解决类型擦除与多态发生的冲突。[2]
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    class DateInterval extends Pair<LocalDate> {
    public void setSecond(LocalDate second) {
    ...
    }
    }
    // 上述类擦除后会变成
    class DateInterval extends Pair {
    public void setSecond(LocalDate second) {
    ...
    }
    }
    // 但会从Pair类中继承一个方法
    class Pair {
    public void setSecond(Object second) {
    ...
    }
    }
    // 桥方法
    public void setSecond(Object second) { setSecond((Date) second); }
  • 大多数 Java 泛型限制都是由类型擦除引起的。
  • 不能用类型参数代替基本类型。
  • 虚拟机中的对象总有一个特定的非泛型类型。
  • 不能实例化参数化类型的数组。
  • 不能实例化类型变置。
  • 不能构造泛型数组。
  • 带有超类型限定的通配符可以向泛型对象写人,带有子类型限定的通配符可以从泛型对象读取。

  1. 不太懂 ↩︎

  2. 道理理解但还需要更详细的文档补充 ↩︎