假设以下类存根:
public class Foo<T> {
private Class<T> type;
public Foo<T> () {}
}
我可以将泛型类型T
存储到构造函数中的字段type
中,而不将构造函数的签名更改为“public Foo<T> (Class<T> type)
”吗?
如果是,怎么样?如果不是,为什么?
“type = T
”似乎不起作用。
答案 0 :(得分:9)
否 - 类型擦除意味着您必须在执行时提供某些内容。您可以提供T
或Class<T>
的实例,但类本身只会将每次出现的T替换为Object
。
这种东西是Java的泛型与.NET中的最大缺点之一。 (另一方面,方差的故事更强 - 如果更混乱 - 在Java中比在.NET中。)
答案 1 :(得分:4)
正如thread中所说,
示例列表&lt;整数&gt;
list.get (index).getClass()
将 不 为您提供存储在列表中的对象类型:
由于类型参数在编译时被擦除,它们在运行时不存在(对不起Jon,execution time):因此,您无法通过java中的反射获得泛型类型信息。
桌子上有更多reification的情况(Java 7?),并且会促进你的目标。
有人会希望一个输入T的坏类型会引发一个Cast异常,它会在执行时显示用于T的原始类型,但是唉,这也不起作用。
考虑以下测试类:
import java.util.ArrayList;
/**
* @param <T>
*/
public class StoreGerenericTypeInField<T>
{
private T myT = null;
private ArrayList<T> list = new ArrayList<T>();
private void setT(final T aT) { myT = aT; }
/**
* Attempt to do private strange initialization with T, in the hope to provoke a cast exception
*/
public StoreGerenericTypeInField()
{
StringBuilder aFirstType = new StringBuilder();
StringBuffer aSecondType = new StringBuffer();
this.list.add((T)aFirstType);
this.list.add((T)aSecondType);
System.out.println(this.list.get(0).getClass().getName());
System.out.println(this.list.get(1).getClass().getName());
setT((T)aFirstType);
System.out.println(this.myT.getClass().getName());
setT((T)aSecondType);
System.out.println(this.myT.getClass().getName());
}
/**
* @param args
*/
public static void main(String[] args)
{
StoreGerenericTypeInField<Integer> s = new StoreGerenericTypeInField<Integer>();
}
}
构造函数尝试将讨厌的东西存储到其T变量(或其List of T)中...并且一切运行顺利!?
打印:
java.lang.StringBuilder
java.lang.StringBuffer
java.lang.StringBuilder
java.lang.StringBuffer
类型擦除本身就是not to blame ...这是类型擦除(java新手)的组合和 不安全的转换 (java旧版旧功能),这使得T在执行时真正无法实现(直到您真正尝试将其与“T
”特定方法一起使用)
答案 2 :(得分:1)
那么,为什么不在课堂上有一个T实例呢?我的意思是,如果情况并非如此,T会给你带来什么?所以,如果你有T x,那么你可以使用x.GetType()。
答案 3 :(得分:-2)
确实
type = T.getClass();
工作?
答案 4 :(得分:-2)
你应该试试这个:
type = T.GetType();