简体   繁体   English

可比接口声明

[英]Declaration of Comparable interface

When the Comparable interface was made generic, the declaration became Comparable接口变得通用时,声明就变成了

interface Comparable<T>

Really it should be something like 真的应该是这样的

interface Comparable<T extends Comparable<T>>

It makes no sense for the T to not extend Comparable because implementors must ensure that T不能扩展Comparable是没有意义的,因为实现者必须确保这一点

a.compareTo(b)

and

b.compareTo(a)

always have opposite signums. 总是有相反的迹象。

I have always assumed that the reason for getting the declaration "wrong" was something to do with the problems of generifying an existing interface, but I can't really explain it. 我一直认为获得声明“错误”的原因与生成现有界面的问题有关,但我无法解释它。

Does anyone have any insights? 有没有人有任何见解?

Really it should be something like 真的应该是这样的

interface Comparable<T extends Comparable<T>>

But that doesn't really give you anything that you don't get with interface Comparable<T> . 但这并没有真正给你任何你用interface Comparable<T>得不到的东西。

You mention the thing about a.compareTo(b) and b.compareTo(a) , but note that your declaration ( interface Comparable<T extends Comparable<T>> ) doesn't actually ensure that if a.compareTo(b) is valid, that b.compareTo(a) compiles. 你提到了关于a.compareTo(b)b.compareTo(a)的事情,但请注意你的声明( interface Comparable<T extends Comparable<T>> )实际上并不确保如果a.compareTo(b)是有效的, b.compareTo(a)编译。 If a is Comparable<T> , a.compareTo(b) requires that b be T , which is also Comparable<T> , so b.compareTo() takes a T . 如果aComparable<T> ,则a.compareTo(b)要求bT ,也是Comparable<T> ,因此b.compareTo()T That doesn't prove that b.compareTo(a) works, as a is a Comparable<T> . 这并不能证明b.compareTo(a)有效,因为a是一个Comparable<T> As a case in point, consider class Foo implements Comparable<Foo> , and class Bar implements Comparable<Foo> . 作为一个例子,考虑class Foo implements Comparable<Foo>class Bar implements Comparable<Foo> If a is of type Bar and b is of type Foo , then with your declaration of Comparable , a.compareTo(b) compiles but b.compareTo(a) doesn't compile (which is also the same thing that happens with the original declaration of Comparable ). 如果aBar类型而bFoo类型,那么使用Comparable的声明, a.compareTo(b)编译但b.compareTo(a)不编译(这也与原始版本相同)可Comparable声明)。 To have a bound that guarantees that when a.compareTo(b) works, that b.compareTo(a) also works, you would need to have something like interface Comparable<T extends Comparable<Comparable<T>>> , but that would be a useless interface because nobody has a T that is comparable to Comparable<T> . 要有一个绑定,保证当a.compareTo(b)工作时, b.compareTo(a)也可以工作,你需要有类似interface Comparable<T extends Comparable<Comparable<T>>> ,但那样做是无用的接口,因为没有人具有T即相当于Comparable<T>

More fundamentally, the purpose of adding a bound in Generics is to allow you to compile something that wouldn't compile, or would require a cast, without the bound. 更基本的是,在泛型中添加一个绑定的目的是允许你编译一些不能编译的东西,或者需要一个没有绑定的强制转换。 Remember, Java checks that code is type-safe at compile-time -- it will only allow you to compile something it knows is possible with the types declared at compile-time (unless you add explicit casts, in which case you take responsibility for the correctness of the conversion). 请记住,Java会在编译时检查代码是否类型安全 - 它只允许您使用在编译时声明的类型编译它知道的内容(除非您添加显式强制转换,在这种情况下,您负责转换的正确性)。 So adding a bound will not increase type-safety -- with or without the bound, the Java compiler will only compile code that is provably type-safe (except for explicit casts or raw type conversions). 因此,添加绑定不会增加类型安全性 - 无论有没有绑定,Java编译器只会编译可证明类型安全的代码(显式强制转换或原始类型转换除外)。 The difference that a bound makes is that by adding constraints, it allows Java to accept more code as type-safe, because the constraints allow Java to deduce the correctness where it wasn't able to before. 绑定的不同之处在于,通过添加约束,它允许Java接受更多类型安全的代码,因为约束允许Java推断出之前无法实现的正确性。 So a bound should only be added when it will allow you to compile something you couldn't without the bound, or would need to add explicit casts without the bound. 所以只有在允许你编译你不能没有绑定的东西时才能添加一个绑定,或者需要在没有绑定的情况下添加显式的强制转换。 Otherwise, what's the point of adding complexity for no benefit? 否则,增加复杂性没有任何好处的重点是什么?

Here, you are not going to find any realistic use cases of code that would compile with your declaration of Comparable but would not compile with the original declaration. 在这里,您不会找到任何可以使用您的Comparable声明编译但不会使用原始声明进行编译的代码的实际用例。 The only realistic use cases I've seen where a declaration interface Foo<T extends Foo<T>> would allow something to compile that wouldn't with interface Foo<T> is in something like the Builder pattern, where Foo<T> has a method that returns a T , and since we know that T is a subtype of Foo<T> , we can go from a Foo<T> to a Foo<T> and chain these operations, without knowing the specific type of T . 我见过的唯一现实用例,声明interface Foo<T extends Foo<T>>将允许编译的东西不会与interface Foo<T>类似于Builder模式,其中Foo<T>有一个返回T的方法,因为我们知道TFoo<T>的子类型,我们可以从Foo<T>转到Foo<T>并链接这些操作,而不知道T的具体类型。 But this is not the case with Comparable -- Comparable doesn't have a method that returns T . 但是Comparable的情况并非如此 - Comparable没有返回T的方法。

If you have a class or method that takes in a comparable type that it needs to sort or order, it is going to have to be a generic method or class that requires the type be comparable to itself (eg class SortedList<T extends Comparable<? super T>> or <T extends Comparable<? super T>> void sort(List<T>) ). 如果你有一个类或方法,它需要一个类似的类型,它需要排序或排序,它将必须是一个通用的方法或类,要求类型与自己相当(例如, class SortedList<T extends Comparable<? super T>><T extends Comparable<? super T>> void sort(List<T>) )。 No bound in the declaration of Comparable can ensure that the type is comparable to itself. Comparable声明中的任何约束都不能确保该类型Comparable自身相当。

If someone decides to write a class where a type is comparable to something completely unrelated (even something that is not Comparable ), then that's fine from a type-safety point of view. 如果有人决定编写一个类型与完全不相关的类型(甚至是不可Comparable东西)的类,那么从类型安全的角度来看这很好。 Yes, you pointed out that it probably violates the documentation of .compareTo() , but that is a code behavior issue, not a type-safety issue. 是的,您指出它可能违反.compareTo()的文档,但这是代码行为问题,而不是类型安全问题。 Their class will probably not be very useful because it will not satisfy the bounds of most places which use Comparable , which will likely have bounds that require that the type be comparable to itself. 他们的类可能不会非常有用,因为它不会满足大多数使用Comparable地方的边界,这可能会限制要求类型与其自身相当。 If there is a place that takes Comparable that doesn't have a bound requiring the type to be comparable to itself, then they can use their class there, but that is still type-safe, because the fact that the place didn't require the type to be comparable to itself means that its own code doesn't rely on that fact to compile safely (or they used explicit casts in which case they take responsibility for the correctness). 如果有一个地方需要Comparable没有绑定要求类型与自己相比,那么他们可以在那里使用他们的类,但这仍然是类型安全的,因为这个地方不需要与自身相当的类型意味着它自己的代码不依赖于这个事实来安全地编译(或者它们使用显式转换,在这种情况下它们负责正确性)。 In any case, that someone could potentially write a (mostly useless and maybe violates documentation) class that is comparable to something not comparable doesn't affect your ability to write your own class that is comparable to itself, and there is no type-safety reason to add any bounds. 在任何情况下,有人可能会编写一个(大多数是无用的,可能违反文档)类,这个类与不具有可比性的东西相比,不会影响你编写自己的类的能力,而这个类与自身相当,而且没有类型安全添加任何边界的原因。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM