为什么Collections.sort(List<T>)
有签名:
public static <T extends Comparable<? super T>> void sort(List<T> list)
而不是:
public static <T extends Comparable<T>> void sort(List<? extends T> list)
答案 0 :(得分:19)
您提议的签名可能适用于Java-8。但是在以前的Java版本中,类型推断并不那么聪明。请考虑您有List<java.sql.Date>
。请注意java.sql.Date
扩展了java.util.Date
,它实现了Comparable<java.util.Date>
。编译时
List<java.sql.Date> list = new ArrayList<>();
Collections.sort(list);
它完全适用于Java-7。此处T
推断为java.sql.Date
,实际上Comparable<java.util.Date>
为Comparable<? super java.sql.Date>
。但是,让我们试试你的签名:
public static <T extends Comparable<T>> void sort(List<? extends T> list) {}
List<java.sql.Date> list = new ArrayList<>();
sort(list);
此处T
应推断为java.util.Date
。但是,Java 7规范不允许这样的推断。因此,此代码可以使用Java-8编译,但在Java-7下编译时会失败:
Main.java:14: error: method sort in class Main cannot be applied to given types;
sort(list);
^
required: List<? extends T>
found: List<Date>
reason: inferred type does not conform to declared bound(s)
inferred: Date
bound(s): Comparable<Date>
where T is a type-variable:
T extends Comparable<T> declared in method <T>sort(List<? extends T>)
1 error
Java-8中的类型推断得到了极大的改进。现在专用于单独的JLS chapter 18,而在Java-7中,规则were更加简单。
答案 1 :(得分:9)
// 0
public static <T extends Comparable<? super T>> void sort0(List<T> list)
// 1
public static <T extends Comparable<T>> void sort1(List<? extends T> list)
这些签名之所以不同,是因为它们对T
定义中Comparable
类型与T
的类型参数之间的关系提出了不同的要求。
假设您有这个类:
class A implements Comparable<Object> { ... }
然后,如果你有
List<A> list = ... ;
sort0(list); // works
sort1(list); // fails
sort1
失败的原因是没有类型T
既可以与自身相比,也可以是列表中的超类型。 s型。
事实证明,类A
格式不正确,因为Comparable
的对象需要满足某些要求。特别是逆转比较应该反转结果的符号。我们可以将A
的实例与Object
进行比较,反之亦然,因此违反了此要求。但请注意,这是Comparable
的语义的要求,并不是由类型系统强加的。仅考虑类型系统,两个sort
声明确实不同。
答案 2 :(得分:4)
它们有所不同,因为? super T
的限制性比T
更少。它是Lower Bounded Wildcard(链接的Java教程,部分说)
术语
List<Integer>
比List<? super Integer>
更具限制性,因为前者仅匹配类型Integer
的列表,而后者匹配任何类型的列表Integer
的超类型Integer
1}}。
将T
替换为T
,这意味着java.lang.Object
或 a OrderItem::whereBetween(
'created_at',
[
DB::raw("CONVERT_TZ('$date 09:00:00', '+00:00', '-06:00')"),
DB::raw("CONVERT_TZ('$date 18:00:00', '+00:00', '-06:00')")
]
)->count();
。