Java 泛型-得到类?

我有一个名单,程序是这样的: public class MyList<T>。有没有什么方法可以使用 T 变量来获取类的名称(这样我就可以从 MyList中知道 T 是否是 String、 Socket 等等) ?

编辑: 没关系,找到答案 给你

191856 次浏览

You are seeing the result of Type Erasure. From that page...

When a generic type is instantiated, the compiler translates those types by a technique called type erasure — a process where the compiler removes all information related to type parameters and type arguments within a class or method. Type erasure enables Java applications that use generics to maintain binary compatibility with Java libraries and applications that were created before generics.

For instance, Box<String> is translated to type Box, which is called the raw type — a raw type is a generic class or interface name without any type arguments. This means that you can't find out what type of Object a generic class is using at runtime.

This also looks like this question which has a pretty good answer as well.

Short answer: You can't.

Long answer:

Due to the way generics is implemented in Java, the generic type T is not kept at runtime. Still, you can use a private data member:

public class Foo<T>
{
private Class<T> type;


public Foo(Class<T> type) { this.type = type; }
}

Usage example:

Foo<Integer> test = new Foo<Integer>(Integer.class);

I'm not 100% sure if this works in all cases (needs at least Java 1.5):

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;


public class Main
{
public class A
{
}


public class B extends A
{
}




public Map<A, B> map = new HashMap<Main.A, Main.B>();


public static void main(String[] args)
{


try
{
Field field = Main.class.getField("map");
System.out.println("Field " + field.getName() + " is of type " + field.getType().getSimpleName());


Type genericType = field.getGenericType();


if(genericType instanceof ParameterizedType)
{
ParameterizedType type = (ParameterizedType) genericType;
Type[] typeArguments = type.getActualTypeArguments();


for(Type typeArgument : typeArguments)
{
Class<?> classType = ((Class<?>)typeArgument);
System.out.println("Field " + field.getName() + " has a parameterized type of " + classType.getSimpleName());
}
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
}

This will output:

Field map is of type Map
Field map has a parameterized type of A
Field map has a parameterized type of B

I'm able to get the Class of the generic type this way:

class MyList<T> {
Class<T> clazz = (Class<T>) DAOUtil.getTypeArguments(MyList.class, this.getClass()).get(0);
}

You need two functions from this file: http://code.google.com/p/hibernate-generic-dao/source/browse/trunk/dao/src/main/java/com/googlecode/genericdao/dao/DAOUtil.java

For more explanation: http://www.artima.com/weblogs/viewpost.jsp?thread=208860

I like the solution from

http://www.nautsch.net/2008/10/28/class-von-type-parameter-java-generics/

public class Dada<T> {


private Class<T> typeOfT;


@SuppressWarnings("unchecked")
public Dada() {
this.typeOfT = (Class<T>)
((ParameterizedType)getClass()
.getGenericSuperclass())
.getActualTypeArguments()[0];
}
...