java.util.Comparator.naturalOrder采用< T扩展Comparable&lt ;?超级T并返回Comparator< T>. - 为什么? [英] java.util.Comparator.naturalOrder takes a <T extends Comparable<? super T>> and returns a Comparator<T> - why?

查看:96
本文介绍了java.util.Comparator.naturalOrder采用< T扩展Comparable&lt ;?超级T并返回Comparator< T>. - 为什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

(如果这是重复的,请为我指出正确的答案!我搜索并阅读了几个(> 5)相关问题,但似乎没有发现.还查看了泛型常见问题解答和其他来源...)

显然,当集合类使用比较器时,对于参数化类型T,它应该具有类型Comparator<? super T>.而且您会看到很多地方,例如 Comparator.naturalOrder() T extends Comparable<? super T>上参数化,但返回Comparator<T>.我试图在我的集合类中保留一个字段,该字段保存用户指定的比较器或Comparator.naturalOrder比较器.

我无法正常工作.我所有相关的问题是:

  1. 如何正确使用Comparator.naturalOrder?
    • 我可以做我想做的事吗?有一个存储用户提供的比较器或naturalOrder比较器的字段?
  2. 鉴于大多数集合类(在框架中)是在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:

  1. 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?
  2. Given that most collection classes (in the framework) are parameterized on T not T implements Comparable<? super T>, so that's the design pattern chosen, how is naturalOrder 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采用&lt; T扩展Comparable&lt ;?超级T并返回Comparator&lt; T&gt;. - 为什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆