首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Java :在运行时是否也保存了关于泛型类型的任何元信息?

Java :在运行时是否也保存了关于泛型类型的任何元信息?
EN

Stack Overflow用户
提问于 2017-08-21 17:45:41
回答 6查看 1.4K关注 0票数 4

背景

我对Java泛型的理解是,它完全是编译时特性(主要关注类型安全检查)。任何泛型类的类型信息在运行时丢失(类型擦除)。

尽管如此,我仍然看到许多框架()似乎也可以在运行时利用类型信息。例如,google 提供者。guice提供程序可以在运行时实例化并提供其泛型类型的新实例。

代码语言:javascript
复制
class Container
{
     @Inject   
     public Container(Provider<Content> contentProvider)
     {
     //This works at Runtime... but How ??? 
     //When type's are not even preserved at runtime, how does the Provider knows it has to instantiate an object of type 'Content' 
     Content content = contentProvider.get();   
     }
}

问题

  1. 是否有任何与运行时保存的泛型类型有关的信息。如果是,什么?If no,而不是像google这样的库是如何在内部运行的(上面的例子)
  2. 泛型不仅仅是编译时的安全性吗?与之一样,是否有任何用例(除了确保编译时的安全),在使用泛型时可以获得优势?
EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2017-08-21 18:32:34

当然,支持类是泛型的信息。

换句话说:当您反编译ArrayList.class时,您会发现这个类允许一个泛型类型参数的提示。换句话说:类文件包含信息。使用反射,可以在运行时检查此元信息。

但是,当您有另一个使用某些List<Integer>对象的类时--则在编译的类中找不到关于"list使用Integer“的信息--除非您使用一些特定的模式,例如,概述了这里

因此,答案基本上是:对于几乎所有实际相关的用例,“泛型”只是编译时间。

示例:

代码语言:javascript
复制
public class GenericsExample<T> {
  private T member;   
  public T foo(T bar) {
     return member;
  }
}

现在运行: javap -p -c GenericsExample

代码语言:javascript
复制
Compiled from "GenericsExample.java"
public class GenericsExample<T> {
  private T member;

  public GenericsExample();
    Code:
       0: aload_0       
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return        

  public T foo(T);
    Code:
       0: aload_0       
       1: getfield      #2                  // Field member:Ljava/lang/Object;
       4: areturn       
}

如您所见,反编译器理解该类使用泛型类型T。有关更多细节,请参见这里那里

票数 3
EN

Stack Overflow用户

发布于 2017-08-21 18:06:00

如果一个类扩展了一个泛型类或接口,并为参数提供了一个具体的类型,那么该类型可以通过Class.getGenericSuperclass()获得。该方法(在本例中)将返回包含实际参数化的ParameterizedType

例如,如果您有:

代码语言:javascript
复制
class BigIntegerList extends ArrayList<BigInteger> {}

然后你就可以:

代码语言:javascript
复制
Class<BigIntegerList> fooClass = BigIntegerList.class;
Type superclass = fooClass.getGenericSuperclass();
if (superclass instanceof ParameterizedType) {
  ParameterizedType parameterized = (ParameterizedType) superclass;
  Type[] parameterizations = parameterized.getActualTypeArguments();
  System.out.println(Arrays.toString(parameterizations));
  // prints: "[class java.math.BigInteger]"
}

这确实被像Guice这样的反射密集型库所使用。另一个例子是Jackson的TypeReference,它可以让您以BigDecimal列表的形式读取JSON列表(例如)。

票数 3
EN

Stack Overflow用户

发布于 2017-08-21 17:49:16

如果不知道要为特定的类使用哪种类型,泛型是一个很好的编程方法。在运行时,将根据类的输入设置泛型类类型。它主要用于编译时安全性。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45802927

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档