我有一个泛型类,Foo<T>。在Foo的一个方法中,我想获取T类型的类实例,但我无法调用T.class。
使用T.class绕过它的首选方法是什么?
我有一个泛型类,Foo<T>。在Foo的一个方法中,我想获取T类型的类实例,但我无法调用T.class。
使用T.class绕过它的首选方法是什么?
当前回答
你不能这样做,因为类型删除。另请参阅堆栈溢出问题Java泛型-类型擦除-何时发生以及发生什么。
其他回答
然而,有一个小漏洞:如果您将Foo类定义为抽象类。这意味着您必须将类实例化为:
Foo<MyType> myFoo = new Foo<MyType>(){};
(注意末端的双撑杆。)
现在,您可以在运行时检索T的类型:
Type mySuperclass = myFoo.getClass().getGenericSuperclass();
Type tType = ((ParameterizedType)mySuperclass).getActualTypeArguments()[0];
然而,请注意,mySuperclass必须是实际定义T的最终类型的类定义的超类。
它也不是很优雅,但你必须决定你喜欢新的Foo<MyType>(){}还是新的Foo<MyType<(MyType.class);在您的代码中。
例如:
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.NoSuchElementException;
/**
* Captures and silently ignores stack exceptions upon popping.
*/
public abstract class SilentStack<E> extends ArrayDeque<E> {
public E pop() {
try {
return super.pop();
}
catch( NoSuchElementException nsee ) {
return create();
}
}
public E create() {
try {
Type sooper = getClass().getGenericSuperclass();
Type t = ((ParameterizedType)sooper).getActualTypeArguments()[ 0 ];
return (E)(Class.forName( t.toString() ).newInstance());
}
catch( Exception e ) {
return null;
}
}
}
然后:
public class Main {
// Note the braces...
private Deque<String> stack = new SilentStack<String>(){};
public static void main( String args[] ) {
// Returns a new instance of String.
String s = stack.pop();
System.out.printf( "s = '%s'\n", s );
}
}
我假设,既然你有一个泛型类,你会有一个这样的变量:
private T t;
(此变量需要在构造函数中取值)
在这种情况下,您可以简单地创建以下方法:
Class<T> getClassOfInstance()
{
return (Class<T>) t.getClass();
}
希望它有帮助!
我想将T.class传递给一个使用Generics的方法
readFile方法读取文件名指定的.csv文件,文件名为fullpath。可以有不同内容的csv文件,因此我需要传递模型文件类,以便获得适当的对象。因为这是读取csv文件,所以我想以通用的方式进行。由于某种原因或其他原因,上述解决方案都不适用于我。我需要使用类别<?扩展T>类型以使其工作。我使用opencsv库解析CSV文件。
private <T>List<T> readFile(String fileName, Class<? extends T> type) {
List<T> dataList = new ArrayList<T>();
try {
File file = new File(fileName);
Reader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
Reader headerReader = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
CSVReader csvReader = new CSVReader(headerReader);
// create csv bean reader
CsvToBean<T> csvToBean = new CsvToBeanBuilder(reader)
.withType(type)
.withIgnoreLeadingWhiteSpace(true)
.build();
dataList = csvToBean.parse();
}
catch (Exception ex) {
logger.error("Error: ", ex);
}
return dataList;
}
这是readFile方法的调用方式
List<RigSurfaceCSV> rigSurfaceCSVDataList = readSurfaceFile(surfaceFileName, RigSurfaceCSV.class);
你不能这样做,因为类型删除。另请参阅堆栈溢出问题Java泛型-类型擦除-何时发生以及发生什么。
这是一个有效的解决方案:
@SuppressWarnings("unchecked")
private Class<T> getGenericTypeClass() {
try {
String className = ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0].getTypeName();
Class<?> clazz = Class.forName(className);
return (Class<T>) clazz;
} catch (Exception e) {
throw new IllegalStateException("Class is not parametrized with generic type!!! Please use extends <> ");
}
}
笔记:只能用作超类
必须使用类型化类进行扩展(Child扩展Generic<Integer>)
OR
必须创建为匿名实现(new Generic<Integer>(){};)