如何获取泛型T的真实类型
2024-01-08 10:44:45
    		一.Type类是啥
Type是Java 编程语言中所有类型的公共高级接口(官方解释),也就是Java中所有类型的“爹”,它并不是我们平常工作中经常使用的 int、String、List、Map等数据类型,而是从Java语言角度来说,对基本类型、引用类型向上的抽象;
Type体系中类型的包括:
- 原始类型(Type):不仅仅包含我们平常所指的类,还包括枚举、数组、注解等
- 参数化类型(ParameterizedType):就是我们平常所用到的泛型List<String>、Map<K,V>,Set<T>,Class<?>
- 数组类型(GenericArrayType):并不是我们工作中所使用的数组String[] 、byte[],而是带有泛型的数组,即T[]
- 类型变量(TypeVariable):比如 T a
- 基本类型(Class):原始类型,每个类(貌似接口也有)都会有个Class对象
我们重点看一下ParameterizedType?:
public interface ParameterizedType extends Type {
    // 获取<>中实际的类型参数,以Type数组形式返回
    Type[] getActualTypeArguments();
    // 获取<>前面的类型
    Type getRawType();
    // 如果这个类型是某个类型所属,则获取这个所有者的类型,否则返回null,比如Map.Entry<Sting,String>,会返回Map
    Type getOwnerType();
}
?
具体可参考:https://www.jianshu.com/p/0f3eda48d611
二.如何获得泛型T的真实类型
反射拿到泛型接口的实现类的实际泛型类型
定义一个泛型接口和他的实现类:
public interface IMessageSender<T,K> {
    K sendMsg(T msg);
}
public class SmsMessageImpl implements IMessageSender<String, List<Integer>>, Serializable{
    @Override
    public List<Integer> sendMsg(String msg) {
        return new ArrayList<>();
    }
}通过反射拿到SmsMessageImpl实现的接口里面的T,K的真实类型:
    /**
     * 反射拿到泛型接口的实现类的实际泛型类型
     */
    public static void testClassGenericActualType1(){
        System.out.println("testClassGenericActualType1开始");
        //getGenericInterfaces返回表示由此对象表示的类或接口直接实现的接口的Type
        //IMessageSender<String, List<Integer>>
        Type genericInterfaces1 = SmsMessageImpl.class.getGenericInterfaces()[0];
        //Serializable
        Type genericInterfaces2 = SmsMessageImpl.class.getGenericInterfaces()[1];
        //输出的是sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl
        System.out.println(genericInterfaces1.getClass());
        //输出的是class java.lang.Class
        System.out.println(genericInterfaces2.getClass());
        //返回表示此类型实际类型参数的 Type对象的数组
        Type[] actualTypeArguments = ((ParameterizedType)genericInterfaces1).getActualTypeArguments();
        //class java.lang.String , java.util.List<java.lang.Integer>
        //这边直接拿到了SmsMessageImpl中两个实际泛型类型
        System.out.println("反射拿到泛型接口的实现类的实际泛型类型:"+actualTypeArguments[0] + " , "+ actualTypeArguments[1]);
        System.out.println("testClassGenericActualType1结束");
    }输出结果是:
testClassGenericActualType1开始
class sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl
class java.lang.Class
反射拿到泛型接口的实现类的实际泛型类型:class java.lang.String , java.util.List<java.lang.Integer>
testClassGenericActualType1结束反射拿到父类的实际泛型类型?
定义一个泛型类,和他的子类:
public class MessageSender <T>{
}
public class SmsMessage extends MessageSender<String>{
}
通过对SmsMessage的class对象进行反射拿到父类里面真实的String类型:
public static void testClassGenericActualType2(){
        System.out.println("testClassGenericActualType2开始");
        //返回表示此 Class 所表示的实体(类、接口、基本类型或 void)的直接超类的Type。如果超类是 
        //参数化类型,则返回的 Type 对象必须准确反映源代码中所使用的实际类型参数
        Type genericSuperclass = SmsMessage.class.getGenericSuperclass();
        Type[] actualTypeArguments = ((ParameterizedType) genericSuperclass).getActualTypeArguments();
        System.out.println("反射拿到父类的实际泛型类型:"+actualTypeArguments[0]);
        System.out.println("testClassGenericActualType2结束");
    }?输出结果是:
testClassGenericActualType2开始
反射拿到父类的实际泛型类型:class java.lang.String
testClassGenericActualType2结束反射获取方法参数上泛型参数的实际类型
我们定义了一个verify方法:
public class Main {
    public static void main(String[] args) throws NoSuchMethodException{
        testMethodGenericActualType();
    }
    /**
     * 获取方法参数上泛型参数的实际类型
     * @throws NoSuchMethodException
     */
    public static void testMethodGenericActualType() throws NoSuchMethodException {
        System.out.println("testMethodGenericActualType开始");
        //反射拿到Main.class中的verify方法
        Method method = Main.class.getMethod("verify", Map.class);
        //反射拿到verify方法的参数列表的第一个参数
        Parameter parameter = method.getParameters()[0];
        Type type = parameter.getParameterizedType();
        //由于参数是带泛型的,因此type的实际类型是ParameterizedType,
        //可以强制转换为ParameterizedType,然后获取参数Map中的两个泛型参数: <String,Integer>
        Type[] actualTypeArguments = ((ParameterizedType) type).getActualTypeArguments();
        System.out.println("获取方法参数上泛型参数的实际类型:"+actualTypeArguments[0] + " , " + actualTypeArguments[1]);
        System.out.println("testMethodGenericActualType结束");
    }
    /**
     * 用于测试获取方法参数上泛型参数的实际类型
     * @param map
     */
    public void verify(Map<String,Integer> map){
    }
}输出结果是:
testMethodGenericActualType开始
获取方法参数上泛型参数的实际类型:class java.lang.String , class java.lang.Integer
testMethodGenericActualType结束?反射获取字段上泛型参数的实际类型
public class Main {
    public static void main(String[] args) throws NoSuchFieldException {
        testFieldGenericActualType();
    }
    /**
     * 获取字段上泛型参数的实际类型
     */
    public static void testFieldGenericActualType() throws NoSuchFieldException {
        System.out.println("testFieldGenericActualType开始");
        Field field = Main.class.getDeclaredField("list");
        //获取字段泛型
        ParameterizedType genericType = (ParameterizedType) field.getGenericType();
        Type[] actualTypeArguments = genericType.getActualTypeArguments();
        //得到字段List<String>泛型中的实际类型String
        System.out.println("获取字段上泛型参数的实际类型:"+actualTypeArguments[0]);
        System.out.println("testFieldGenericActualType结束");
    }
    private List<String> list;
}输出结果是:
testFieldGenericActualType开始
获取字段上泛型参数的实际类型:class java.lang.String
testFieldGenericActualType结束
    			文章来源:https://blog.csdn.net/qq_42426725/article/details/135386286
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
    	本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!