为何Apache Commons Range#between与ZonedDateTime配合不符合预期?
Range<ChronoZonedDateTime<?>>能正确编译? 我们逐个分析三个代码片段的编译逻辑:
range1编译正常的原因
Range<ZonedDateTime>完全匹配方法的类型推断规则。Range.between要求泛型参数T实现Comparable<? super T>,而ZonedDateTime本身就实现了Comparable<ZonedDateTime>,完全满足约束。编译器直接推断T为ZonedDateTime,返回的Range<ZonedDateTime>可以直接赋值给range1。range2编译失败的原因
Java泛型默认是不变的——哪怕ZonedDateTime是ChronoZonedDateTime<LocalDate>的子类,Range<ZonedDateTime>和Range<ChronoZonedDateTime<LocalDate>>之间也没有继承关系,不能直接赋值。
另外,编译器会优先根据传入的参数推断T为ZonedDateTime,返回的是Range<ZonedDateTime>,无法转换为Range<ChronoZonedDateTime<LocalDate>>。就算强制指定T为ChronoZonedDateTime<LocalDate>,ZonedDateTime的Comparable实现是Comparable<ZonedDateTime>,和ChronoZonedDateTime<LocalDate>要求的Comparable<ChronoZonedDateTime<? super LocalDate>>不匹配,依然会报错。range3编译正常的原因
ChronoZonedDateTime<?>是通配符类型,它包含所有具体参数化的ChronoZonedDateTime子类型(包括ChronoZonedDateTime<LocalDate>)。此时编译器可以推断T为ChronoZonedDateTime<?>:ZonedDateTime是ChronoZonedDateTime<?>的实例,符合方法参数要求;ChronoZonedDateTime<?>实现了Comparable<ChronoZonedDateTime<?>>,满足T extends Comparable<? super T>的约束;
最终返回的Range<ChronoZonedDateTime<?>>可以直接赋值给range3。
内容的提问来源于stack exchange,提问作者Ramazan

