简体   繁体   English

Java泛型—寻找一种方法来告诉我泛型的超类型

[英]Java generics — looking for a method to tell me the supertype of a generic type

the supertype of 的超类型

SomeClass <Double>  

is

Someclass <T extends Numbers>

and is not 而且不是

SomeClass <Numbers> 

i'm looking for a method returning the supertype of an instance of a generic class. 我正在寻找一种返回泛型类实例的超类型的方法。 Something like getGenericSuperclass() of the of Class ( although can't be exactly like it-- getGenericSuperclass() returns only one class while a generic can extend and be bounded by multiple as in: Class getGenericSuperclass()Class (虽然不能完全一样getGenericSuperclass()仅返回一个类,而泛型可以扩展并受多个限制,如下所示:

Eg.: 例如。:

Someclass <T extends aConcreteClass && anInterface && anotherInterface>

When i run getGenericSuperclass() on an instance of a generic class, i'm getting Object in return. 当我在泛型类的实例上运行getGenericSuperclass()时,我得到了Object作为回报。

Is there such a method anywhere in Java, telling me the supertype of the generic type on which i instantiated an object on? Java中是否有这样的方法可以告诉我实例化对象的泛型的超类型?

//=================== // ===================

EDIT: lengthy comment to @jwa's answer below: 编辑:冗长的评论@jwa的答案如下:

i understand the generics are type-checked at compile time. 我了解泛型是在编译时进行类型检查的。 however, JVM could still bind the types in run-time, as specifically as possible using the outcome of type inference , and return at least the definition of the supertype rather than merely returning Object as the supertype. 但是,JVM仍然可以在运行时绑定类型,特别是使用类型推断的结果,并且至少返回超类型的定义,而不仅仅是返回Object作为超类型。 This info is clearly available in runtime. 该信息显然在运行时可用。 but i gather it's not doing this. 但我知道它没有这样做。

NOTE: haven't yet looked deep into type erasure. 注意:尚未深入研究类型擦除。

//================================= // =================================

EDIT2: EDIT2:

referring to the term "bounded type parameter" in this page, i've been looking for a method to return the object's "bound class(es)", 引用页面中的“绑定类型参数”一词,我一直在寻找一种方法来返回对象的“绑定类”,

which is Comparable in the example 在示例中是可比

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; }
// ...
}

on the same page . 在同一页面上

no trace of it in those pages or anywhere else-- i guess Java not doing it. 在那些页面或其他任何地方都找不到它-我想Java不会这么做。

You need to take a look into "type erasure". 您需要查看“类型擦除”。 Essentially, when your java code is compiled into bytecode the generic information is lost (or "erased"). 本质上,当您将Java代码编译为字节码时,通用信息会丢失(或“擦除”)。 This is why you cannot find any methods for querying the generic typing via the reflection classes. 这就是为什么您找不到通过反射类查询通用类型的任何方法的原因。

I couldn't find a good answer regarding type erasure here on SO, but Wikiepdia seems to have a reasonable description . 我在SO上找不到有关类型擦除的好答案,但Wikiepdia似乎有一个合理的描述

It's worth noting that type erasure was chosen to give backward-compatability between java 1.5 and 1.4. 值得注意的是,选择类​​型擦除是为了在Java 1.5和1.4之间提供向后兼容性。 Other languages have implemented this differently. 其他语言对此的实现方式也有所不同。 For example, .NET has full support for generics in byte code - and does permit such methods as part of its reflection API. 例如,.NET完全支持字节码中的泛型-并且确实允许此类方法作为其反射API的一部分。


Consider this class, which uses typed and non-typed lists: 考虑此类,该类使用类型化和非类型化列表:

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

There is no difference between the way that the two methods are encoded in byte code. 两种方法以字节码进行编码的方式之间没有区别。 We can see this using javap , specifically javap -c CastExample : 我们可以使用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       
}

The exact meaning of each of these operations is not overly important. 这些操作中每个操作的确切含义都不过分重要。 The important thing is that it is calling the exact same operations, there's no distinction between the two. 重要的是它调用的是完全相同的操作,两者之间没有区别。

the supertype of 的超类型

SomeClass <Double> is SomeClass <Double>

Someclass <T extends Numbers> Someclass <T extends Numbers>

The premise of the question is wrong. 问题的前提是错误的。 First of all, Someclass <T extends Numbers> is not syntactically correct as a type in Java. 首先, Someclass <T extends Numbers>在Java上在语法上不正确。

And second, there is no single generic "supertype" of a type. 其次,没有一个类型的单个泛型“超类型”。 The following is a list of some (but not all) supertypes of SomeClass <Double> : 以下是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.)

Yeap, generics aren't covariant in Java, ie List< Number > is not a superclass of List< Double > . 是的,泛型在Java中不是协变的,即List <Number>不是List <Double>的超类。 You should read some info on it, heres a link . 您应该阅读一些相关信息,这里是一个链接

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

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