简体   繁体   English

接口如何与 java 中的 generics 子类型化一起使用?

[英]How interface works with generics subtyping in java?

Consider the following classes.考虑以下类。

class Shape {}
class Circle extends Shape {}
class Rectangle extends Shape {}

class Node <T> {}

// In main method
Node<Circle> circleNode = new Node<>();
Node<Shape> shapeNode = circleNode; // ERROR

Following code will not compile because even though Circle is a subtype of Shape.以下代码不会编译,因为即使 Circle 是 Shape 的子类型。 Because of generics subtyping.因为 generics 子类型。

But now consider the new Node class.但现在考虑新的节点 class。

class Node<T> implements Comparable<T> {
    public int compareTo(T obj) { /* ... */ }
    // ...
}

// In main method
Node<String> stringNode = new Node<>();
Comparable<String> comparable = stringNode;

Following code successfully compile.以下代码成功编译。 But there is no explanation on Java Docs.但是 Java Docs 上没有解释。 How implementing an interface make it compile successfully.实现接口如何使其编译成功。 And I didn't understand what happened exactly.我不明白到底发生了什么。

You're comparing apples and oranges.你在比较苹果和橘子。

In your example, Node<Shape> is to Node<Circle> as List<Animal> is to List<Dog> .在您的示例中, Node<Shape>Node<Circle> ,因为List<Animal>List<Dog> However, Comparable<String> is to Node<String> as List<Animal> is to ArrayList<Animal> .但是, Comparable<String>Node<String> ,因为List<Animal>ArrayList<Animal>

If you can have this parallelism clear in mind, all you need to remember is that a List<Dog> is not a List<Animal> and you have your answer.如果您可以清楚地记住这种并行性,那么您只需要记住List<Dog>不是List<Animal>并且您有答案。

stringNode is a Node<String> , and that means assigning that variable to a Comparable<String> -typed variable only requires the base type's relationship. stringNode是一个Node<String> ,这意味着将该变量分配给Comparable<String>类型的变量只需要基本类型的关系。 That's because the declaration Node<T> implements Comparable<T> makes Node a Comparable subtype.这是因为声明Node<T> implements Comparable<T>使Node成为Comparable子类型。 With the type parameter being exactly the same, that makes Comparable<String> assignable from Node<String> (just as List<String> is assignable from ArrayList<String> )由于 type 参数完全相同,这使得Comparable<String>可以从Node<String> > 赋值(就像List<String>可以从ArrayList<String>赋值一样)

In other words, the difference is not due to "implementing an interface make it compile successfully" ... it's due to the fact that Node<Shape> is not assignable from Node<Circle> (which you seem to understand), whether node is an interface or not.换句话说,差异不是由于“实现接口使其编译成功” ......这是由于Node<Shape>不能从Node<Circle>分配(您似乎理解),无论节点是不是一个接口。

In 2nd example you're saying that for a given T a Node<T> is a Comparable<T> .在第二个示例中,您说对于给定的T a Node<T>Comparable<T> Thus, for T = String you have Node<String> is a Comparable<String> .因此,对于T = String你有Node<String>是一个Comparable<String>

However in 1st example you have 2 different types T and U where T is a U but there is nothing that says that Node<T> is a Node<U> .但是,在第一个示例中,您有 2 种不同的类型TU ,其中TU但没有任何内容表明Node<T>Node<U>

You might want to look for covariance and contravariance to learn more on this topic.您可能需要寻找协变逆变来了解有关此主题的更多信息。

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

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