简体   繁体   English

区别“ <T extends Comparable<T> &gt;“和” <T extends Comparable<Comparable<T> &gt;&gt;”?

[英]Difference between “<T extends Comparable<T>>” and “<T extends Comparable<Comparable<T>>>”?

In the expression <T extends Comparable<T>> in a signature like 在表达式<T extends Comparable<T>>中的签名就像

public static <T extends Comparable<T>> foo(T x) { ... }

the description of T depends recursively on Comparable<T> . T的描述依赖于Comparable<T>

If T extends Comparable<T> , and Comparable<T> extends Comparable<Comparable<T>> , doesn't it follow that T extends Comparable<Comparable<T>> ? 如果T扩展了Comparable<T> ,并且Comparable<T>扩展了Comparable<Comparable<T>> ,那么它是否会延伸T扩展Comparable<Comparable<T>>

IOW, is the extends relationship transitive? IOW, extends关系是否可传递?

If so, why isn't 如果是这样,为什么不呢

public static <T extends Comparable<Comparable<T>>> int compare(T x, T y) {
    return x.compareTo(y);
}

equivalent to 相当于

public static <T extends Comparable<T>> int compare(T x, T y) {
    return x.compareTo(y);
}

? In fact, the last definition compiles, whereas the one above it fails to compile, with the error 事实上,最后一个定义编译,而上面的定义无法编译,错误

comp.java:7: compareTo(java.lang.Comparable<T>) in 
java.lang.Comparable<java.lang.Comparable<T>> cannot be applied to (T)
            return x.compareTo(y);

Thanks! 谢谢!

You've made an incorrect logical jump here, I think. 我想你在这里做了一个不正确的逻辑跳跃。

T extends Comparable<T>

does not imply that 并不意味着

Comparable<T> extends Comparable<Comparable<T>>

Short analogy : 简短的比喻

Suppose a rock-crusher is any material that can crush rock , and rock just happens to be capable of crushing itself. 假设一个岩石破碎机是任何可以压碎岩石的材料, 岩石恰好能够破碎自己。 So rock is a rock-crusher. 所以摇滚是一种摇滚破碎机。 Does this mean that rock can crush any substance which can crush rock? 这是否意味着岩石可以粉碎任何可以粉碎岩石的物质? Clearly not: steel might also be a rock-crusher while rock might not crush steel. 显然不是: 钢铁也可能是碎石机,而岩石可能不会压碎钢铁。


Long (code-based) analogy : 长(基于代码)类比

Suppose I have an interface, Additive<T> , which can be used to describe any type to which you may perform an add operation on a T object and get back a T . 假设我有一个Additive<T>接口,可用于描述您可以对T对象执行add操作并返回T任何类型。

Now let's say I have some method whose signature looks like this: 现在让我们说我有一些方法的签名如下:

public static <T extends Additive<T>> add(T x, T y) { ... }

Since x must be of a type to which I can add a T , this method could be implemented as follows: 由于x必须是我可以添加T的类型,因此可以按如下方式实现此方法:

return x.add(y);

Make sense? 说得通? OK, great; 好,很好; but now let's make the assumption you've made in your question: that Additive<T> must extend Additive<Additive<T>> ; 但现在让我们假设你在你的问题中做出的假设: Additive<T>必须扩展Additive<Additive<T>> ; if this is the case then I can assume that I can add to x an instance of any type implementing Additive<T> . 如果是这种情况,那么我可以假设我可以向x添加任何实现 Additive<T> 类型的实例。

Here's where the assumption breaks down. 这是假设失败的地方。 I might have a type, say... 我可能有类型,说...

// A 32-bit integral number supporting addition
public class Int32 implements Additive<Int32> { ... }

That would make sense, right? 这有道理,对吗? I could also have something like this: 我也可以这样:

// A list of 32-bit integral numbers supporting appending
public class Int32List implements Additive<Int32> { ... }

Now, if T extends Additive<T> implied that Additive<T> extends Additive<Additive<T>> then I should be able to do this: 现在,如果T extends Additive<T>暗示Additive<T> extends Additive<Additive<T>>那么我应该能够这样做:

Additive<Int32> x = new Int32(5);
Additive<Int32> y = x.add(new Int32List());

Does that make any sense? 这有任何意义吗?

There's nothing special about 没什么特别的

<T extends Comparable<T>>

Consider 考虑

public class Foo implements Comparable<Foo>{
     int compareTo(Foo x);
}

I don't even think we can say that it's defined recursively, it's just self referential. 我甚至不认为我们可以说它是递归定义的,它只是自我引用。

Comparable<T> extends Comparable<Comparable<T>>

Perhaps I misunderstand what relationship you are conveying, but this statement is untrue. 也许我误解了你传达的关系,但这种说法是不真实的。 Comparable<T> does not extend anything. Comparable<T>不会扩展任何内容。

The fundamental issue to keep in mind is that Java generics are scoped by the compilation unit and compile time. 要记住的基本问题是Java泛型由编译单元和编译时限限定。 It is just syntactic sugar! 这只是语法糖! (How many times I forget this and end up reasoning precisely the way you do, as if Java Generics actually implied a generic type system in runtime .) (多少次我忘记了这一点并最终推断出你的方式, 就像 Java Generics 在运行时实际上暗示了泛型类型系统一样 。)

From the spec : 规格

The scope of a class' type parameter is the entire declaration of the class 
including the type parameter section itself. 

Therefore, type parameters can appear as parts of their own bounds, or as 
bounds of other type parameters declared in the same section.

There is no recursion, and no new types are defined. 没有递归,也没有定义新类型。

To wit: 以机智:

package so_6949760;

import java.util.HashMap;

public class SweetCompilingGenerics {

    @SuppressWarnings("serial")
    public static class Sweet<X> extends HashMap<X, Sweet<X>> {}

    public static void main(String[] args) {
        Sweet<String> sweetStr = new Sweet<String>();
        Sweet<Sweet<Integer>> whatever = new Sweet<SweetCompilingGenerics.Sweet<Integer>>();

        assert sweetStr.getClass().equals(whatever.getClass()) : "who made generics a runtime mechanism?";
        assert sweetStr.getClass() == whatever.getClass() : "who made generics a runtime mechanism?";

        System.out.format("Is %s a Sweet<String> ?\n", sweetStr.getClass().getCanonicalName());
        System.out.format("Is %s a Sweet<Sweet<Integer>> ?\n", whatever.getClass().getCanonicalName());
    }
}

Will output the sweet secret: 将输出甜蜜的秘密:

Is so_6949760.SweetCompilingGenerics.Sweet a Sweet<String> ? 
Is so_6949760.SweetCompilingGenerics.Sweet a Sweet<Sweet<Integer>> ?

May I be so forward to offer an advice to a fellow geek? 我是否可以如此向一位极客提供建议? Always read the specification . 始终阅读规范

[post accept edit]: Just found this highly informative article by IBM . [post accept edit]:刚刚发现IBM的这篇内容丰富的文章 That pretty much addresses all of OP's questions. 这几乎解决了OP的所有问题。 (Recommended). (推荐的)。

Comparable<T> does not extend Comparable<Comparable<T>> (just because T extends Comparable<T> ) in the same way that List<String> does not extend List<Object> (just because String extends Object ). Comparable<T>不会扩展Comparable<Comparable<T>> (仅因为T扩展Comparable<T> ),就像List<String>不扩展List<Object> (因为String扩展了Object )。

Please refer to this document from Oracle to read more about generics and inheritance. 请参阅Oracle的此文档以阅读有关泛型和继承的更多信息。

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

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