ParameterizedType类型设置默认值

本文探讨了在Java开发中处理ParameterizedType类型时如何设置默认值,尤其是在Gson反序列化中遇到的问题。文章指出,直接将ParameterizedType转换为Class会导致ClassCastException。解释了Object、Class和Type接口的区别,并详细阐述了ParameterizedType的原理。为了解决这个问题,提出了使用空泛型对象的json表示(如'[]')作为默认值的解决方案,以适配List、Map和Set三种泛型类型的空值情况。

背景

开发过程中,我们为了减少错误发生,会将很多异常数据返回默认值,如Gson反序列化,我们加工后 ,即使传入空json和Type,其fromJson的返回均能返回默认值。但是维护的基础库发生异常。java.lang.ClassCastException: com.google.gson.internal.GsonGsonGsonTypes$ParameterizedTypeI cannot be cast to java.lang.Class。因使用了((Class<?>) type).newInstance()获取默认值, 将所有类型type强转为class导致错误。

 Object obj = gson.fromJson(json, type);
   return null == obj ? (T) ((Class<?>) type).newInstance() : (T) obj ;// 强转类型错误

原理

  1. Object:

Object 是一个类。 每个类都继承自 Object,所有对象(包括数组)都实现了这个类的方法。

  1. Class:

Class 是一个类(不是class)。该类没有公共构造函数,相反,类对象由Java虚拟机自动构建,用于表示JVM运行时类或接口的信息。Class类的构造函数被设计为私有的,这意味着我们不能通过new的方式来创建Class对象,只有JVM才能创建该类的实例。

  1. Type:

Type 是一个接口。Type是Java编程语言中所有类型的通用超级接口,这些包括:

  • 原始类型(raw types):包括类和接口。基本数据类型和不涉及泛型的所有引用类型(类、接口、数组)均是Class类型。比如String
    s、String s1[]、List list等对应的类型均是Class类型。
  • 参数化类型(parameterized types):也叫泛型,例如List是一个参数化类型。Map<String,Integer> map 等对应的类型均是ParameterizedType类型
  • 数组类型(array types):带有泛型的数组类型,也就是带有参数化类或者接口所表示的数组对应的类型,例如 List s[]、Map<String,Integer> map[]等对应的类型均是GenericArrayType类型,而List s[]、Map map[]是Class类型
  • 类型变量(type variables):也叫泛型变量,即泛型中的变量,例如:T、K、V等变量,可以表示任何类。
  • 基本数据类型(primitive types):byte、short、boolean、char、int、long、float、double
    八大基本数据类型。
  • 通配符类型(WildcardType) :通配符对应的类型,例如 List<? extends Object> 中?对应的类型

如果我们使用普通的java bean类,那是class类型,可以强转,但是参数化类型 不同于class。

ParameterizedType就是参数化类型的意思
声明类型中带有“<>”的都是参数化类型,比如List,Map<String,Long>

  • getActualTypeArguments()返回Type[],即“<>”里的参数,比如Map<String,Integer>
  • getRawType()返回Tpye,得到“<>”前面的类型,比如List
  • getOwnerType()返回Type,返回ParameterizedType类型所在的类的Type。如Map.Entry<String,
    Object>这个参数化类型返回的是Map(因为Map.Entry这个类型所在的类是Map)的类型。

方案

为了达到gson反序列化传空json也能返回默认值的目的,针对ParameterizedType这种情况。
参数化类型List不是Class类型,强转会异常,不能返回默认初始对象,可利用空的泛型gson.toJson后的结果(gson。toJson(new ArrayList())输出‘[]’),反向用fromJson默认值作为json为空时的默认值。
适配了List<> Map<> Set<>(忽略泛型类型)三种泛型为空时的json输出

    private static <T> T getDefaultValueWithType (Type type) throws IllegalAccessException, InstantiationException {
        if(typeinstanceof Class) {
            return (T) ((Class<?>) type).newInstance();
        } else if (type instanceof ParameterizedType) {
            //泛型类型默认值
            ParameterizedType genericType = (ParameterizedType) type;
            if (genericType.getRawType().equals(List.class) ||
                    genericType.getRawType().equals(Set.class)) {
                return gson.fromJson("[]", type);
            } else if(genericType.getRawType().equals(Map.class)) {
                return gson.fromJson("{}", type);
            } else {
                return null;
            }
        } else {
            return null;
        }
    }
//测试时,封装过后的gson工具类
Map<String, Integer> test= GsonTool.fromJson(null, (new TypeToken<Map<String, Integer>>() {}).getType());
//fromJson 内部调用getDefaultValueWithType 返回默认初始化值
       
        System.out.println("get default obj size "+test.size() + " " + GSON.toJson(test));
       
 其他不常用类型默认返回null 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值