Java :T extends Comparable<? super T> 和 T extends Comparable<T>的区别
目录
- 一. 简介
- 二. 两个类型变量 的区别
- 1. T extends Comparable<T>
- 2. T extends Comparable<? super T>
- 3. 限制的 “松” 与 “紧”
- 三. 哪个函数可以使用 LocalDate?
- 1. 先明确LocalDate的Comparable实现关系
- 2. public static <T extends Comparable< T >> minmax(T[] a)的约束是什么?
- 3. 为什么LocalDate不满足该约束?
- 4. 编译器会如何处理?
- 四.结论
一. 简介
在《Java 核心技术1》中有两个函数,看起来有点困难,其中一个函数不能使用LocalDate 类型。今天来对比一下这两个函数的区别。这两个函数为:
- public static <T extends Comparable> Pair minmax(T[] a)
- public static <T extends Comparable <? super T>> Pair minmax(T[] a)
两个泛型函数的函数名、返回值 和参数都是一样的。唯一的区别就是类型变量 不一样,两个类型变量如下: - 第一个类型变量 T extends Comparable
- 第二个类型变量 T extends Comparable <? super T>
二. 两个类型变量 的区别
1. T extends Comparable
要求T必须直接实现Comparable< T >,即T只能与自身类型的对象比较。
例如:
若Dog implements Comparable< Dog >,则Dog满足此限制,可作为T传入。
但若Dog extends Animal,且Animal implements Comparable< Animal >(而Dog未单独实现Comparable< Dog >),则Dog不满足此限制 —— 因为Dog的比较能力是针对Animal(超类),而非自身Dog,因此无法作为T传入。
2. T extends Comparable<? super T>
允许 T 实现Comparable< S >,其中S是T的超类(S super T)。即T不仅可以与自身比较,还可以与 “父类类型” 的对象比较(借助继承的比较能力)。
例如:
延续上面的例子:Dog extends Animal,Animal implements Comparable< Animal >。此时Dog虽然未实现Comparable< Dog >,但继承了Animal的Comparable< Animal >能力(Animal是Dog的超类,即Animal super Dog),因此Dog满足T extends Comparable<? super T>,可作为T传入。
3. 限制的 “松” 与 “紧”
T extends Comparable< T >是更严格的限制:仅允许T与自身类型比较,不兼容 “通过父类继承比较能力” 的场景。
T extends Comparable<? super T>是更宽松的限制:允许T与自身或其超类比较,兼容更多继承场景(如子类复用父类的比较逻辑)。
因此,第二个声明的适用范围更广,能处理更多类型的数组(如上述Dog[]),而第一个声明仅能处理 “自身实现了与自身比较” 的类型(如Dog implements Comparable)。
三. 哪个函数可以使用 LocalDate?
public static <T extends Comparable< T >> Pair< T > minmax(T[] a)不能用于LocalDate,核心在于 LocalDate实现的Comparable接口类型参数与该方法的泛型约束不匹配 ,结合LocalDate的继承关系可具体分析如下:
1. 先明确LocalDate的Comparable实现关系
根据描述:
- LocalDate实现了ChronoLocalDate接口(即LocalDate IS-A ChronoLocalDate);
- ChronoLocalDate接口本身扩展了Comparable< ChronoLocalDate >(即ChronoLocalDate implements Comparable< ChronoLocalDate >)。
因此,LocalDate通过继承间接实现的是Comparable< ChronoLocalDate >,而非Comparable< LocalDate >。
简单说:LocalDate的比较能力是 “可以与ChronoLocalDate类型的对象比较”,而不是 “只能与LocalDate自身类型比较”。
2. public static <T extends Comparable< T >> minmax(T[] a)的约束是什么?
该方法要求泛型参数T必须满足:T直接实现Comparable< T >,即 **T必须能与 “自身类型T” 比较 **。
用符号表示:T的比较接口必须是Comparable< T >,而不能是Comparable< S >(S是T的父类或其他类型)。
3. 为什么LocalDate不满足该约束?
当T为LocalDate时,该方法要求LocalDate必须实现Comparable< LocalDate >,但实际情况是:
LocalDate实现的是Comparable< ChronoLocalDate >(因为ChronoLocalDate是它的父接口,且父接口定义了与ChronoLocalDate比较)。
此时,Comparable的类型参数是ChronoLocalDate(T的父类),而非T自身(LocalDate),因此 **LocalDate不满足T extends Comparable的约束 **。
4. 编译器会如何处理?
若强行用LocalDate[]调用第二个方法(T extends Comparable< T >),编译器会报错。原因是:
编译器会检查LocalDate是否符合 “T extends Comparable< T >”—— 即是否存在LocalDate implements Comparable< LocalDate >。但实际LocalDate的Comparable参数是ChronoLocalDate,与T(LocalDate)不匹配,因此拒绝通过编译。
对比:为什么第一个方法可以用?
第一个方法public static <T extends Comparable<? super T>> minmax(T[] a)的约束是 “T可以实现Comparable< S >,其中S是T的超类(S super T)”。
对于LocalDate:
T是LocalDate,S可以是ChronoLocalDate(因为ChronoLocalDate是LocalDate的超类);
LocalDate实现的Comparable< ChronoLocalDate >恰好满足 “Comparable<? super LocalDate>”(ChronoLocalDate是LocalDate的超类)。
因此,LocalDate符合第一个方法的约束,可以正常调用。
四.结论
public static <T extends Comparable< T >> minmax(T[] a)的限制更严格:它要求T必须能与自身类型比较(Comparable)。而LocalDate只能与 超类ChronoLocalDate 比较(Comparable< ChronoLocalDate >),不满足 “与自身比较” 的约束,因此该方法无法用于LocalDate。
这也体现了<? super T>的优势:通过允许Comparable的参数是T的超类,放宽了约束,兼容了更多像LocalDate这样 “通过父类实现比较能力” 的场景。