繁体   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>>>”?

在表达式<T extends Comparable<T>>中的签名就像

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

T的描述依赖于Comparable<T>

如果T扩展了Comparable<T> ,并且Comparable<T>扩展了Comparable<Comparable<T>> ,那么它是否会延伸T扩展Comparable<Comparable<T>>

IOW, extends关系是否可传递?

如果是这样,为什么不呢

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

相当于

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

事实上,最后一个定义编译,而上面的定义无法编译,错误

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);

谢谢!

我想你在这里做了一个不正确的逻辑跳跃。

T extends Comparable<T>

并不意味着

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

简短的比喻

假设一个岩石破碎机是任何可以压碎岩石的材料, 岩石恰好能够破碎自己。 所以摇滚是一种摇滚破碎机。 这是否意味着岩石可以粉碎任何可以粉碎岩石的物质? 显然不是: 钢铁也可能是碎石机,而岩石可能不会压碎钢铁。


长(基于代码)类比

假设我有一个Additive<T>接口,可用于描述您可以对T对象执行add操作并返回T任何类型。

现在让我们说我有一些方法的签名如下:

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

由于x必须是我可以添加T的类型,因此可以按如下方式实现此方法:

return x.add(y);

说得通? 好,很好; 但现在让我们假设你在你的问题中做出的假设: Additive<T>必须扩展Additive<Additive<T>> ; 如果是这种情况,那么我可以假设我可以向x添加任何实现 Additive<T> 类型的实例。

这是假设失败的地方。 我可能有类型,说...

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

这有道理,对吗? 我也可以这样:

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

现在,如果T extends Additive<T>暗示Additive<T> extends Additive<Additive<T>>那么我应该能够这样做:

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

这有任何意义吗?

没什么特别的

<T extends Comparable<T>>

考虑

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

我甚至不认为我们可以说它是递归定义的,它只是自我引用。

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

也许我误解了你传达的关系,但这种说法是不真实的。 Comparable<T>不会扩展任何内容。

要记住的基本问题是Java泛型由编译单元和编译时限限定。 这只是语法糖! (多少次我忘记了这一点并最终推断出你的方式, 就像 Java Generics 在运行时实际上暗示了泛型类型系统一样 。)

规格

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.

没有递归,也没有定义新类型。

以机智:

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());
    }
}

将输出甜蜜的秘密:

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

我是否可以如此向一位极客提供建议? 始终阅读规范

[post accept edit]:刚刚发现IBM的这篇内容丰富的文章 这几乎解决了OP的所有问题。 (推荐的)。

Comparable<T>不会扩展Comparable<Comparable<T>> (仅因为T扩展Comparable<T> ),就像List<String>不扩展List<Object> (因为String扩展了Object )。

请参阅Oracle的此文档以阅读有关泛型和继承的更多信息。

暂无
暂无

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

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