从本质上讲,你是在问是否有办法告诉编译器,“嘿,这一种方法要求类型参数匹配比在类级别定义的更具体的边界”。这在Java中是不可能的。这样的功能可能很有用,但我也希望令人困惑和/或复杂。
也没有办法通过当前泛型的实现方式使类型安全;不是,如果你想避免要求一个.例如,您提出了如下建议:Stream.sorted()
Comparator
public interface Stream<T> {
<C extends Comparable<? super T>> Stream<T> sorted(Class<C> clazz);
} // other Stream methods omitted for brevity
遗憾的是,无法保证可从 中分配。请考虑以下层次结构:Class<C>
Class<T>
public class Foo implements Comparable<Foo> { /* implementation */ }
public class Bar extends Foo {}
public class Qux extends Foo {}
您现在可以拥有一个元素,但尝试像元素一样对其进行排序。Stream
Bar
Stream
Qux
Stream<Bar> stream = barCollection.stream().sorted(Qux.class);
由于两者都匹配,因此没有编译时错误,因此没有添加类型安全。此外,要求参数的含义是它将用于转换。在运行时,如上所示,这仍然会导致 s。如果不用于转换,则该参数完全无用;我甚至认为这是有害的。Bar
Qux
Comparable<? super Foo>
Class
ClassCastException
Class
下一个合乎逻辑的步骤是尝试并需要扩展以及。例如:C
T
Comparable<? super T>
<C extends T & Comparable<? super T>> Stream<T> sorted(Class<C> clazz);
这在Java中也是不可能的,并且会导致编译错误:“类型参数不能跟在其他边界后面”。即使这是可能的,我也不认为它能解决所有问题(如果有的话)。
一些相关的说明。
关于:不是使此方法类型安全,而是.确保可以比较元素。为了说明这一点,按元素的自然顺序对 a 进行排序的类型安全方法是:Stream.sorted(Comparator)
Stream
Comparator
Comparator
Stream
Stream<String> stream = stringCollection.stream().sorted(Comparator.naturalOrder());
这是类型安全的,因为需要其类型参数扩展 。如果 的泛型类型未扩展,则边界将不匹配,从而导致编译错误。但同样,这是要求元素是*的,而根本不在乎。naturalOrder()
Comparable
Stream
Comparable
Comparator
Comparable
Stream
那么问题来了,为什么开发人员首先要包含一个无参数的方法呢?这似乎是出于历史原因,并在Holger对另一个问题的回答中进行了解释。sorted
Stream
* 在这种情况下,比较器
要求元素具有可比性
。通常,比较器
显然能够处理它所定义的任何类型的类型。