java.util.Comparator.naturalOrder采用< T扩展Comparable< ;?超级T并返回Comparator< T>. - 为什么? [英] java.util.Comparator.naturalOrder takes a <T extends Comparable<? super T>> and returns a Comparator<T> - why?
问题描述
(如果这是重复的,请为我指出正确的答案!我搜索并阅读了几个(> 5)相关问题,但似乎没有发现.还查看了泛型常见问题解答和其他来源...)>
显然,当集合类使用比较器时,对于参数化类型T
,它应该具有类型Comparator<? super T>
.而且您会看到很多地方,例如 Comparator.naturalOrder()
在T extends Comparable<? super T>
上参数化,但返回Comparator<T>
.我试图在我的集合类中保留一个字段,该字段保存用户指定的比较器或Comparator.naturalOrder
比较器.
我无法正常工作.我所有相关的问题是:
- 如何正确使用
Comparator.naturalOrder
?- 我可以做我想做的事吗?有一个存储用户提供的比较器或
naturalOrder
比较器的字段?
- 我可以做我想做的事吗?有一个存储用户提供的比较器或
- 鉴于大多数集合类(在框架中)是在
T
而不是T implements Comparable<? super T>
上进行参数化的,所以这是选择的设计模式,naturalOrder
很有用,因为它需要后者的有界通配符,而不是无约束的类型参数?
谢谢!
以下是带有编译器错误的实际示例:
所以:如果我在某个T不受限制的类中有这样的代码(就像在所有现有集合类中一样):
class Foo<T> {
private Comparator<? super T> comparator;
public void someMethod(Comparator<? super T> comparator)
{
this.comparator = comparator; // no compile error
this.comparator = Comparator.naturalOrder(); // incompatible types
}
}
出现此错误:
Error:(331, 50) java: incompatible types: inferred type does not conform to upper bound(s)
inferred: T
upper bound(s): java.lang.Comparable<? super T>
因此,如果我决定放弃? super T
的优势,那么我将会:
class Foo<T> {
private Comparator<T> comparator;
public void someMethod(ComparatorT> comparator)
{
this.comparator = comparator; // no compile error
this.comparator = Comparator.naturalOrder(); // incompatible types
}
}
我在哪里
Error:(nnn, 50) java: incompatible types: inference variable T has incompatible bounds
equality constraints: T
upper bounds: java.lang.Comparable<? super T>
此编译:
import java.util.*;
class Foo<T extends Comparable<? super T>> {
private Comparator<T> comparator;
public void someMethod(Comparator<T> comparator)
{
this.comparator = comparator; // no compile error
this.comparator = Comparator.<T>naturalOrder(); // <T> is optional, compiler can infer
}
}
最简单的思考方式是:您尝试将T类型与Comparator接口一起使用,这对它施加了某些要求(特别是它有一个花哨的递归要求,即T必须实现Comparable接口).在泛化(?)类时,无需强加这样的要求,因此编译器不满意.您对T的要求必须与使用它的类一样强.
您对自然排序方法的功能感到困惑.它只需要一个实现Comparable的类,并为其创建默认的Comparator.没办法-您无法为不可比的事物创建比较器.
您希望TreeMap要求Comparable,但您不希望这样做,因为只要提供了Comparator,使用不具有可比性的东西就是一种有效的情况.因此TreeMap最终不执行Comparable,而只是在运行时显式强制转换(并引发异常).
(If this is a duplicate please point me to the right answer! I searched and read several (>5) related questions but none seemed on the mark. Also looked at the Generics FAQ and other sources...)
It is apparently proper practice that when a collection class takes a comparator it should have the type Comparator<? super T>
for your parameterized type T
. And you can see that lots of places, e.g., TreeMap
. Okay.
My problem is working with Comparator.naturalOrder()
which is parameterized on T extends Comparable<? super T>
but returns a Comparator<T>
. I'm trying to have a field in my collection class that holds either the user-specified comparator or the Comparator.naturalOrder
comparator.
I can't get it to work. My questions, all related, are:
- How is
Comparator.naturalOrder
properly used?- And can I do what I want which is have a field where I store either a user-supplied comparator or the
naturalOrder
comparator?
- And can I do what I want which is have a field where I store either a user-supplied comparator or the
- Given that most collection classes (in the framework) are parameterized on
T
notT implements Comparable<? super T>
, so that's the design pattern chosen, how isnaturalOrder
useful since it requires the latter bounded wildcard, not the unconstrained type parameter?
Thanks!
Here follows the actual examples with compiler errors:
So: If I have code like this in some class where T has no bounds (as in all existing collection classes):
class Foo<T> {
private Comparator<? super T> comparator;
public void someMethod(Comparator<? super T> comparator)
{
this.comparator = comparator; // no compile error
this.comparator = Comparator.naturalOrder(); // incompatible types
}
}
with this error:
Error:(331, 50) java: incompatible types: inferred type does not conform to upper bound(s)
inferred: T
upper bound(s): java.lang.Comparable<? super T>
So if I decide to forgo the advantages of ? super T
then I have:
class Foo<T> {
private Comparator<T> comparator;
public void someMethod(ComparatorT> comparator)
{
this.comparator = comparator; // no compile error
this.comparator = Comparator.naturalOrder(); // incompatible types
}
}
where I have
Error:(nnn, 50) java: incompatible types: inference variable T has incompatible bounds
equality constraints: T
upper bounds: java.lang.Comparable<? super T>
This compiles:
import java.util.*;
class Foo<T extends Comparable<? super T>> {
private Comparator<T> comparator;
public void someMethod(Comparator<T> comparator)
{
this.comparator = comparator; // no compile error
this.comparator = Comparator.<T>naturalOrder(); // <T> is optional, compiler can infer
}
}
The simplest way to think about it is this: you are trying to use type T with the Comparator interface, which imposes certain requirements on it (in particular it has that fancy recursive requirement that T must implement Comparable interface). You do not impose such requirement when genericising (?) your class, so compiler is not happy. Your requirements on T must be as strong as the class that you are using it with.
You are confused about what natural ordering method does. It just takes a class which implements Comparable and creates the default Comparator for it. No way around it -- you can't create a Comparator for something that is not Comparable.
You want TreeMap to require Comparable, but you can't, because it is a valid case to use something that is not comparable, as long as you have provided a Comparator. So TreeMap ends up not enforcing Comparable and just casts explicitly at runtime (and throws an exception).
这篇关于java.util.Comparator.naturalOrder采用< T扩展Comparable< ;?超级T并返回Comparator< T>. - 为什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!