-1-泛型和Class类
从JDK5以后,Java的Class类增加了泛型功能,从而允许使用泛型来限制Class类。如果Class对应的类暂时未知,则使用Class<?>
,通过在反射中使用泛型,可以避免使用泛型生成的对象需要强制类型转换。
public class CrazyitObjectTest
{
public static Object getInstance(String clsName)
{
try
{
Class cls = Class.forName(clsName);
return cls.newInstance();
}
catch (Exception e)
{
e.printStackTrace();
return null;
}
}
}
上面代码将返回一个新的对象,但由于这个对象的类型是Object,因此需要强制类型转换:
Date d = (Date) CrazyitObjectTest.getInstance(“java.util.Date”);
使用泛型之后的效果,不需要类型转换
public class CrazyitObjectTest
{
public static <T> T getInstance(Class<T> cls)
{
try
{
return cls.newInstance();
}
catch (Exception e)
{
e.printStackTrace();
return null;
}
}
}
Date d = CrazyitObjectTest.getInstance(Date.class);
Intent intent = CrazyitObjectTest.getInstance(Intent.class);
-2-使用反射来获取泛型消息
获取了成员变量的Field对象后,就可以很容易地获取该成员变量的数据类型,如下:
//获取成员变量f的类型
Class<?> a = f.getType();
但这种方式只对普通类型的成员变量有效。如果该成员变量的类型是有泛型类型的类型,如果Map<String , Integer>
类型,则不能准确地得到该成员变量的泛型参数。
通过下面方式来获取该成员变量的泛型类型:
//获取成员变量f的泛型类型
Type gType = f.getGenericType();
然后将Type对象强制类型转换为ParameterizedType对象,ParameterizedType代表被参数化的类型,也就是增加了泛型限制的类型。ParameterizedType类型提供了如下两个方法:
(1)getRawType():返回没有泛型消息的原始类型;
(2)getActualTypeArguments():返回泛型参数的类型。
例子:
public class GenericTest
{
private Map<String , Integer> score;
public static void showGeneric() throws Exception
{
Class<GenericTest> clazz = GenericTest.class;
Field f = clazz.getDeclaredField("score");
//直接使用getType()取出类型只对普通类型的成员变量有效
Class<?> a = f.getType();
//下面将看到仅输出java.util.Map
Log.d("GenericTest" , "score的类型是:" + a);
//获取成员变量f的泛型类型
Type gType = f.getGenericType();
//如果gType类型是ParameterizedType对象
if (gType instanceof ParameterizedType)
{
//强制类型转换
ParameterizedType pType = (ParameterizedType) gType;
//获取原始类型
Type rType = pType.getRawType();
Log.d("GenericTest" , "原始类型是:" + rType);
Type[] tArgs = pType.getActualTypeArguments();
Log.d("GenericTest" , "泛型消息是:");
for (int i = 0 ; i < tArgs.length ; i++)
{
Log.d("GenericTest" , "第" + i + "泛型类型是:" + tArgs[i]);
}
}
}
}
输出:
score的类型是:interface java.util.Map
原始类型是:interface java.util.Map
泛型消息是:
第0泛型类型是:class java.lang.String
第1泛型类型是:class java.lang.Integer
例子2(将泛型类型转换为Gson解析时需要的Type类型)
public abstract class BaseCallBack<T>
{
public Type mType;
static Type getSuperclassTypeParameter(Class<?> subClass)
{
Type superclass = subClass.getGenericSuperclass();
if (superclass instanceof Class)
{
throw new RuntimeException("Missing type parameter.");
}
ParameterizedType parameterized = (ParameterizedType) superclass;
return $Gson$Types.canonicalize(parameterized.getActualTypeArguments()[0]);
}
public BaseCallBack()
{
mType = getSuperclassTypeParameter(getClass());
}
}
Type是java.lang.reflect包下的一个接口,该接口代表所有类型的公共高级接口,Class是Type接口的实现类。