反射专题5

-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接口的实现类。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值