为什么SomeClass 不等同于Java泛型类型中的SomeClass ?

时间:2022-02-20 19:27:11

I noticed the specificaition for Collections.sort:

我注意到了Collections.sort的具体说明:

public static <T> void sort(List<T> list, Comparator<? super T> c)

Why is the "? super" necessary here? If ClassB extends ClassA, then wouldn't we have a guarantee that a Comparator<ClassA> would be able to compare two ClassB objects anyway, without the "? super" part?

为什么这里需要“超级”?如果ClassB扩展了ClassA,那么我们不能保证Comparator 能够比较两个ClassB对象,而没有“?super”部分吗?

In other words, given this code:

换句话说,鉴于此代码:

List<ClassB> list = . . . ;
Comparator<ClassA> comp = . . . ;
Collections.sort(list, comp);

why isn't the compiler smart enough to know that this is OK even without specifying "? super" for the declaration of Collections.sort()?

为什么编译器不够聪明,即使没有为Collections.sort()的声明指定“?super”,也知道这没关系?

5 个解决方案

#1


7  

Josh Bloch had a talk at Google I/O this year, called Effective Java Reloaded, which you may find interesting. It talks about a mnemonic called "Pecs" (producer extends, consumer super), which explains why you use ? extends T and ? super T in your input parameters (only; never for return types), and when to use which.

Josh Bloch今年在Google I / O上发表了一篇名为Effective Java Reloaded的演讲,您可能会感兴趣。它谈到了一个名为“Pecs”(生产者扩展,消费者超级)的助记符,它解释了你使用它的原因?扩展T和?输入参数中的超级T(仅用于返回类型),以及何时使用哪些。

#2


6  

There's a really nice (but twisty) explanation of this in More Fun with Wildcards.

在使用通配符更有趣的情况下,有一个非常好(但有点曲折)的解释。

#3


1  

This is similar to C#, I just learned about it a couple days ago as to why (the hard way, and then the PDC informative way).

这类似于C#,我刚刚了解了它为什么(艰难的方式,然后是PDC信息方式)。

Assume Dog extends Animal

假设狗延伸动物

Blah<Dog> is not the same as Blah<Animal> they have completely different type signatures even though Dog extends Animal.

Blah 与Blah 不同,即使Dog扩展Animal,它们也有完全不同的类型签名。

For example assume a method on Blah<T>:

例如假设Blah 上的方法:

T Clone();  

In Blah<Dog> this is Dog Clone(); while in Blah<Animal> this is Animal Clone();.

在Blah 这是Dog Clone();而在Blah 这是Animal Clone();.

You need a way to distinguish that the compiler can say that Blah<Dog> has the same public interface of Blah<Animal> and that's what <? super T> indicates - any class used as T can be reduced to its super class in terms of Blah<? super T>.

您需要一种方法来区分编译器可以说Blah 具有与Blah 相同的公共接口,那就是 表示 - 任何用作T的类都可以用Blah 。

(In C# 4.0 this would be Blah<out T> I believe.)

(在C#4.0中,这将是Blah 我相信。)

#4


0  

It's obvious to you that, in the case of Comparator, any ancestor of T would work. But the compiler doesn't know that class Comparator functions like that - it just needs to be told whether it should allow <T> or <? super T>.

很明显,对于比较器来说,任何T的祖先都可以工作。但是编译器不知道类比较器的功能就是这样 - 只需要告诉它是否应该允许 或 。

Viewed another way, yes it's true that any Comparator of an ancestor would work in this case - and the way the library developer says that is to use <? super T>.

从另一个角度来看,是的,祖先的任何比较器都可以在这种情况下工作 - 而且库开发人员说这是使用 。

#5


0  

The simple answer to your question is that the library designer wanted to give the maximum flexibility to the user of the library; this method signature for example allows you to do something like this:

对您的问题的简单回答是,图书馆设计师希望为图书馆的用户提供最大的灵活性;例如,此方法签名允许您执行以下操作:

List<Integer> ints = Arrays.asList(1,2,3);
Comparator<Number> numberComparator = ...;

Collections.sort(ints, numberComparator);

Using the wildcard prevents you from being forced to use a Comparator<Integer>; the fact that the language requires a wildcard to be specified by the library designer enables him or her to either permit or restrict such use.

使用通配符可以防止您被强制使用Comparator ;该语言要求库设计者指定通配符这一事实使他或她能够允许或限制此类使用。

#1


7  

Josh Bloch had a talk at Google I/O this year, called Effective Java Reloaded, which you may find interesting. It talks about a mnemonic called "Pecs" (producer extends, consumer super), which explains why you use ? extends T and ? super T in your input parameters (only; never for return types), and when to use which.

Josh Bloch今年在Google I / O上发表了一篇名为Effective Java Reloaded的演讲,您可能会感兴趣。它谈到了一个名为“Pecs”(生产者扩展,消费者超级)的助记符,它解释了你使用它的原因?扩展T和?输入参数中的超级T(仅用于返回类型),以及何时使用哪些。

#2


6  

There's a really nice (but twisty) explanation of this in More Fun with Wildcards.

在使用通配符更有趣的情况下,有一个非常好(但有点曲折)的解释。

#3


1  

This is similar to C#, I just learned about it a couple days ago as to why (the hard way, and then the PDC informative way).

这类似于C#,我刚刚了解了它为什么(艰难的方式,然后是PDC信息方式)。

Assume Dog extends Animal

假设狗延伸动物

Blah<Dog> is not the same as Blah<Animal> they have completely different type signatures even though Dog extends Animal.

Blah 与Blah 不同,即使Dog扩展Animal,它们也有完全不同的类型签名。

For example assume a method on Blah<T>:

例如假设Blah 上的方法:

T Clone();  

In Blah<Dog> this is Dog Clone(); while in Blah<Animal> this is Animal Clone();.

在Blah 这是Dog Clone();而在Blah 这是Animal Clone();.

You need a way to distinguish that the compiler can say that Blah<Dog> has the same public interface of Blah<Animal> and that's what <? super T> indicates - any class used as T can be reduced to its super class in terms of Blah<? super T>.

您需要一种方法来区分编译器可以说Blah 具有与Blah 相同的公共接口,那就是 表示 - 任何用作T的类都可以用Blah 。

(In C# 4.0 this would be Blah<out T> I believe.)

(在C#4.0中,这将是Blah 我相信。)

#4


0  

It's obvious to you that, in the case of Comparator, any ancestor of T would work. But the compiler doesn't know that class Comparator functions like that - it just needs to be told whether it should allow <T> or <? super T>.

很明显,对于比较器来说,任何T的祖先都可以工作。但是编译器不知道类比较器的功能就是这样 - 只需要告诉它是否应该允许 或 。

Viewed another way, yes it's true that any Comparator of an ancestor would work in this case - and the way the library developer says that is to use <? super T>.

从另一个角度来看,是的,祖先的任何比较器都可以在这种情况下工作 - 而且库开发人员说这是使用 。

#5


0  

The simple answer to your question is that the library designer wanted to give the maximum flexibility to the user of the library; this method signature for example allows you to do something like this:

对您的问题的简单回答是,图书馆设计师希望为图书馆的用户提供最大的灵活性;例如,此方法签名允许您执行以下操作:

List<Integer> ints = Arrays.asList(1,2,3);
Comparator<Number> numberComparator = ...;

Collections.sort(ints, numberComparator);

Using the wildcard prevents you from being forced to use a Comparator<Integer>; the fact that the language requires a wildcard to be specified by the library designer enables him or her to either permit or restrict such use.

使用通配符可以防止您被强制使用Comparator ;该语言要求库设计者指定通配符这一事实使他或她能够允许或限制此类使用。