千家信息网

Java泛型中类型擦除问题怎么解决

发表于:2025-02-23 作者:千家信息网编辑
千家信息网最后更新 2025年02月23日,这篇"Java泛型中类型擦除问题怎么解决"文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇
千家信息网最后更新 2025年02月23日Java泛型中类型擦除问题怎么解决

这篇"Java泛型中类型擦除问题怎么解决"文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇"Java泛型中类型擦除问题怎么解决"文章吧。

假设有两个bean类

/** Test. */@Data@NoArgsConstructor@AllArgsConstructorpublic static class Foo {    public String name;} /** Test. */@Data@NoArgsConstructor@AllArgsConstructorpublic static class Dummy {    public String name;}

以及另一个对象

@NoArgsConstructor@AllArgsConstructor@Datapublic static class Spec {     public String spec;     public T deserializeTo() throws JsonProcessingException {        var mapper = new ObjectMapper();        return (T) mapper.readValue(spec, Foo.class);    }}

可以看到Spec对象中保存了以上两种类型json序列化后的字符串,并提供了方法将string spec 反序列化成相应的类型,比较理想的方式是在反序列化的方法中能够获取到参数类型 T 的实际类型,理论上运行时Spec类型是确定了,因此T也应该是确定的,但是因为类型擦除,所以实际上获取不到他的类型。

按照以下尝试 通过((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()获取泛型类型,经过测试是获取不到的

 @Test    public void test() throws JsonProcessingException {        var foo = new Foo("foo");        var spec = new Spec(mapper.writeValueAsString(foo));        var deserialized = spec.deserializeTo();        Assertions.assertTrue(deserialized instanceof Foo);    }     @NoArgsConstructor    @AllArgsConstructor    @Data    public static class Spec {         public String spec;         private Class getSpecClass() {            return (Class)                    ((ParameterizedType) getClass().getGenericSuperclass())                            .getActualTypeArguments()[0];        }         public T deserializeTo() throws JsonProcessingException {            var mapper = new ObjectMapper();            System.out.println(spec);            return (T) mapper.readValue(spec, getSpecClass());        }    }

会有以下的错误

java.lang.ClassCastException: class java.lang.Class cannot be cast to class java.lang.reflect.ParameterizedType (java.lang.Class and java.lang.reflect.ParameterizedType are in module java.base of loader 'bootstrap')

有两种办法来绕过这个问题

第一种比较简单,就是在创建spec对象时,直接把类型的class传进来,这样就可以直接使用。

第二种是创建spec的子类中使用这个方法就可以获取泛型的类型

@Datapublic abstract static class AbstractSpec {     public String spec;     public AbstractSpec(String spec) {        this.spec = spec;    }     private Class getSpecClass() {        return (Class)                ((ParameterizedType) getClass().getGenericSuperclass())                        .getActualTypeArguments()[0];    }     public T deserializeTo() throws JsonProcessingException {        var mapper = new ObjectMapper();        System.out.println(spec);        return (T) mapper.readValue(spec, getSpecClass());    }} public static class Spec extends AbstractSpec {    public Spec(String spec) {        super(spec);    }} @Testpublic void test() throws JsonProcessingException {    var foo = new Foo("foo");    var spec = new Spec(mapper.writeValueAsString(foo));    var deserialized = spec.deserializeTo();    Assertions.assertTrue(deserialized instanceof Foo);}

这里spec类就可以顺利的被反序列化。

这个和最开始失败的case的差别就是新增了一个子类,主要的差别是getGenericSuperclass的返回值有差异,非子类的情况下,获取到的是Object。

因此理论上子类Spec的类型信息中,实际上是保存了父类中的类型参数信息的,也就是例子中的Foo. 按照 https://stackoverflow.com/questions/42874197/getgenericsuperclass-in-java-how-does-it-work 的方式,可以查看到Spec类的字节码中有相应的类型信息。

$ javap -verbose ./org/apache/flink/kubernetes/operator/controller/GenericTest\$Spec.class | grep Signature  #15 = Utf8               Signature        Start  Length  Slot  Name   SignatureSignature: #19                          // Lorg/apache/flink/kubernetes/operator/controller/GenericTest$AbstractSpec;

以上就是关于"Java泛型中类型擦除问题怎么解决"这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注行业资讯频道。

类型 内容 问题 序列 信息 子类 实际 对象 就是 方法 参数 实际上 差别 文章 方式 理论 知识 篇文章 两个 也就是 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 软件开发怎么配电脑 scum能开4人的服务器吗 2022网络安全公开课 桓台销售采购生产软件开发咨询 一款游戏需要多大的工作站服务器 幼儿园网络安全简单画画 崇明区使用网络技术方案设计 三级计算机网络技术类专业 服务器连接失败怎么办 软件开发方案书文库 天然气软件开发公司 转行做对日软件开发 网络安全问题知多少手抄报 什么情况下会使用数据库 网络安全利润率 四川全盛通网络技术 ar软件开发工程师招聘 企业网络安全等级保护通知 科技金融公司是互联网公司嘛 ktv项目软件开发 多功能网络技术开发口碑推荐 网络安全防范措施滞后 数据库实体图描述 易县国培软件开发服务部 软件开发行业最新资讯 阿里云服务器怎么管理后台 联想服务器如何查询阵列卡 计算机三级网络技术报名要求 上海孚正网络技术有限公司 数据库服务器当前时间
0