简体   繁体   English

嵌套Java通用类型

[英]Nesting Java Generic Types

I'm trying to implement a graph using generics, and I want to use a generic argument for both the nodes and the data within the nodes. 我正在尝试使用泛型来实现图,并且我想对节点和节点中的数据都使用泛型参数。 It works if I do it the first way, but ideally I would like to define it the second way. 如果我以第一种方式进行操作,它将起作用,但理想情况下,我想以第二种方式对其进行定义。

Why doesn't the second way work? 为什么第二种方法不起作用?

//OK
public class AdjacencyListGraph<E, N extends Node<E>> {
}

//Cannot resolve symbol E
public class AdjacencyListGraph<N extends Node<E>> {
}

In the context of java generics the word extends means the upper bound , not the inheritance. 在Java泛型的字扩展的上下文中是指上限 ,而不是继承。 The meaning of that word is overloaded in case of generics. 在泛型的情况下,该词的含义会过载。

Generics were introduced in java to give developers the ability to write more consistent, clean and less buggy code then it was before. Java中引入了泛型,以使开发人员能够编写比以前更一致,更干净且更少错误的代码。 It's all about the development, not the execution. 这全都与开发有关,而不是执行。 There are no generics in the compiled code. 编译后的代码中没有泛型。 However there is some information about actual types in metaspace which you can retrieve via reflection, but it's meta information, not the actual code. 但是,您可以通过反射来获取有关元空间中实际类型的一些信息,但这是元信息,而不是实际代码。

During the compilation generic types are erased and replaced by actual bounds ( https://docs.oracle.com/javase/tutorial/java/generics/genTypes.html ). 在编译期间,通用类型将被删除,并由实际范围( https://docs.oracle.com/javase/tutorial/java/generics/genTypes.html )取代。 And here is the root cause of your problem. 这就是问题的根本原因。 If a provided bound is also generic then compiler is unable to perform type erasure. 如果提供的绑定也是通用的,则编译器将无法执行类型擦除。 It simply dont know by which type it should replace the generic one in the code during compilation. 它只是不知道在编译期间应以哪种类型替换代码中的通用类型。 So you will get compilation error. 所以你会得到编译错误。

//OK
public class AdjacencyListGraph<E, N extends Node<E>> {
}

Here anyway you will have to provide actual type E and so the compiler will be able to resolve the actual bound and perform type erasure. 无论如何,这里您将必须提供实际的类型E,因此编译器将能够解析实际的边界并执行类型擦除。

//Cannot resolve symbol E
public class AdjacencyListGraph<N extends Node<E>> {
}

In this case your bound also becomes generic. 在这种情况下,您的界限也将变得通用。 The compiler do not know the actual type. 编译器不知道实际的类型。 It can be any type. 它可以是任何类型。 So it cant perform type erasure here and gives you a compilation error. 因此,它无法在此处执行类型擦除,并为您提供编译错误。

Also here are some useful resources about generics: http://www.angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.html https://docs.oracle.com/javase/tutorial/java/generics/index.html 另外,这里还有一些有关泛型的有用资源: http : //www.angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.html https://docs.oracle.com/javase/tutorial/java/generics/index.html

The first one is really great. 第一个真的很棒。 Here is info about extends word and it's meaning in the generics context: http://www.angelikalanger.com/GenericsFAQ/FAQSections/TechnicalDetails.html#Does%20extends%20always%20mean%20inheritance ? 这是有关扩展字的信息,其含义在泛型上下文中: http : //www.angelikalanger.com/GenericsFAQ/FAQSections/TechnicalDetails.html#Does%20extends%20always%20mean%20inheritance吗?

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

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