繁体   English   中英

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

[英]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.

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