背景
我对Java泛型的理解是,它完全是编译时特性(主要关注类型安全检查)。任何泛型类的类型信息在运行时丢失(类型擦除)。
尽管如此,我仍然看到许多框架()似乎也可以在运行时利用类型信息。例如,google 提供者。guice提供程序可以在运行时实例化并提供其泛型类型的新实例。
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();
}
}问题
发布于 2017-08-21 18:32:34
当然,支持类是泛型的信息。
换句话说:当您反编译ArrayList.class时,您会发现这个类允许一个泛型类型参数的提示。换句话说:类文件包含元信息。使用反射,可以在运行时检查此元信息。
但是,当您有另一个使用某些List<Integer>对象的类时--则在编译的类中找不到关于"list使用Integer“的信息--除非您使用一些特定的模式,例如,概述了这里。
因此,答案基本上是:对于几乎所有实际相关的用例,“泛型”只是编译时间。
示例:
public class GenericsExample<T> {
private T member;
public T foo(T bar) {
return member;
}
}现在运行: javap -p -c GenericsExample
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
}发布于 2017-08-21 18:06:00
如果一个类扩展了一个泛型类或接口,并为参数提供了一个具体的类型,那么该类型可以通过Class.getGenericSuperclass()获得。该方法(在本例中)将返回包含实际参数化的ParameterizedType。
例如,如果您有:
class BigIntegerList extends ArrayList<BigInteger> {}然后你就可以:
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列表(例如)。
发布于 2017-08-21 17:49:16
如果不知道要为特定的类使用哪种类型,泛型是一个很好的编程方法。在运行时,将根据类的输入设置泛型类类型。它主要用于编译时安全性。
https://stackoverflow.com/questions/45802927
复制相似问题