[英]Supertype casting in generics (Getting the generic supertype of a generic type)
[英]Java generics — looking for a method to tell me the supertype of a generic type
的超类型
SomeClass <Double>
是
Someclass <T extends Numbers>
而且不是
SomeClass <Numbers>
我正在寻找一种返回泛型类实例的超类型的方法。 Class
getGenericSuperclass()
之Class
(虽然不能完全一样getGenericSuperclass()
仅返回一个类,而泛型可以扩展并受多个限制,如下所示:
例如。:
Someclass <T extends aConcreteClass && anInterface && anotherInterface>
当我在泛型类的实例上运行getGenericSuperclass()
时,我得到了Object
作为回报。
Java中是否有这样的方法可以告诉我实例化对象的泛型的超类型?
// ===================
编辑:冗长的评论@jwa的答案如下:
我了解泛型是在编译时进行类型检查的。 但是,JVM仍然可以在运行时绑定类型,特别是使用类型推断的结果,并且至少返回超类型的定义,而不仅仅是返回Object作为超类型。 该信息显然在运行时可用。 但我知道它没有这样做。
注意:尚未深入研究类型擦除。
// =================================
EDIT2:
引用此页面中的“绑定类型参数”一词,我一直在寻找一种方法来返回对象的“绑定类”,
在示例中是可比的
public class Node<T extends Comparable<T>> {
private T data;
private Node<T> next;
public Node(T data, Node<T> next) {
this.data = data;
this.next = next;
}
public T getData() { return data; }
// ...
}
在同一页面上 。
在那些页面或其他任何地方都找不到它-我想Java不会这么做。
您需要查看“类型擦除”。 本质上,当您将Java代码编译为字节码时,通用信息会丢失(或“擦除”)。 这就是为什么您找不到通过反射类查询通用类型的任何方法的原因。
我在SO上找不到有关类型擦除的好答案,但Wikiepdia似乎有一个合理的描述 。
值得注意的是,选择类型擦除是为了在Java 1.5和1.4之间提供向后兼容性。 其他语言对此的实现方式也有所不同。 例如,.NET完全支持字节码中的泛型-并且确实允许此类方法作为其反射API的一部分。
考虑此类,该类使用类型化和非类型化列表:
import java.util.List;
public class CastExample <T extends Object> {
public List<T> typedList;
public List<?> untypedList;
public T getFirstElement() {
return typedList.get(0);
}
public T getFromUntypedArray() {
return (T) untypedList.get(0);
}
}
两种方法以字节码进行编码的方式之间没有区别。 我们可以使用javap
,特别是javap -c CastExample
:
/var/tmp-> javap -c CastExample
Compiled from "CastExample.java"
public class CastExample<T> {
public java.util.List<T> typedList;
public java.util.List<?> untypedList;
public CastExample();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public T getFirstElement();
Code:
0: aload_0
1: getfield #2 // Field typedList:Ljava/util/List;
4: iconst_0
5: invokeinterface #3, 2 // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
10: areturn
public T getFromUntypedArray();
Code:
0: aload_0
1: getfield #4 // Field untypedList:Ljava/util/List;
4: iconst_0
5: invokeinterface #3, 2 // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
10: areturn
}
这些操作中每个操作的确切含义都不过分重要。 重要的是它调用的是完全相同的操作,两者之间没有区别。
的超类型
SomeClass
<Double>
是Someclass
<T extends Numbers>
问题的前提是错误的。 首先, Someclass <T extends Numbers>
在Java上在语法上不正确。
其次,没有一个类型的单个泛型“超类型”。 以下是SomeClass <Double>
的某些(但不是全部)超类型的SomeClass <Double>
:
SomeClass<? extends Number>
SomeClass<? extends Serializable>
SomeClass<? extends Comparable<Double>>
SomeClass<? extends Comparable<? extends Number>>
SomeClass<? extends Comparable<? extends Serializable>>
SomeClass<? extends Comparable<? extends Comparable<Double>>>
SomeClass<? extends Comparable<?>>
SomeClass<? extends Object>
SomeClass<?>
SomeClass<? super Double>
Object
(and if SomeClass has a superclass or interface SuperclassOfSomeClass:)
SuperclassOfSomeClass<Double>
SuperclassOfSomeClass<? extends Number>
... (all of the above for SomeClass repeated for SuperclassOfSomeClass, etc.)
是的,泛型在Java中不是协变的,即List <Number>不是List <Double>的超类。 您应该阅读一些相关信息,这里是一个链接 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.