我尝试使用泛型实现图形,并且我想为节点和节点内的数据使用泛型参数。如果我是第一种方式,它可以工作,但理想情况下我想以第二种方式定义它。
为什么第二种方式不起作用?
//OK
public class AdjacencyListGraph<E, N extends Node<E>> {
}
//Cannot resolve symbol E
public class AdjacencyListGraph<N extends Node<E>> {
}
答案 0 :(得分:2)
在java泛型的上下文中,单词 extends 表示上面的 bound ,而不是继承。在泛型的情况下,该词的含义过载。
在Java中引入了泛型,使开发人员能够编写更加一致,干净且错误较少的代码。这完全是关于开发,而不是执行。编译代码中没有泛型。但是,有一些关于元空间中实际类型的信息可以通过反射检索,但它是元信息,而不是实际代码。
在编译期间,泛型类型将被删除并替换为实际边界(https://docs.oracle.com/javase/tutorial/java/generics/genTypes.html)。这是问题的根本原因。如果提供的绑定也是通用的,则编译器无法执行类型擦除。它根本不知道在编译期间应该用哪种类型替换代码中的泛型。所以你会得到编译错误。
//OK
public class AdjacencyListGraph<E, N extends Node<E>> {
}
无论如何,你必须提供实际类型E,因此编译器将能够解析实际绑定并执行类型擦除。
//Cannot resolve symbol E
public class AdjacencyListGraph<N extends Node<E>> {
}
在这种情况下,你的绑定也变得通用了。编译器不知道实际类型。它可以是任何类型。所以它不能在这里执行类型擦除并给你一个编译错误。
此处还有一些关于泛型的有用资源: http://www.angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.html https://docs.oracle.com/javase/tutorial/java/generics/index.html
第一个真的很棒。以下是有关扩展单词的信息,它在泛型上下文中的含义:http://www.angelikalanger.com/GenericsFAQ/FAQSections/TechnicalDetails.html#Does%20extends%20always%20mean%20inheritance?