java中的类型擦除type erasure示例详解

 更新时间:2023年09月15日 09:46:24   作者:flydean  
泛型是java从JDK 5开始引入的新特性,泛型的引入可以让我们在代码编译的时候就强制检查传入的类型,从而提升了程序的健壮度,泛型可以用在类和接口上,在集合类中非常常见,本文将会讲解泛型导致的类型擦除

举个例子

我们先举一个最简单的例子:

@Slf4j
public class TypeErase {
    public static void main(String[] args) {
        ArrayList<String> stringArrayList = new ArrayList<String>();
        stringArrayList.add("a");
        stringArrayList.add("b");
        action(stringArrayList);
    }
    public static void action(ArrayList<Object> al){
        for(Object o: al)
            log.info("{}",o);
    }
}

上面的例子中,我们定义了一个ArrayList,其中指定的类型是String。

然后调用了action方法,action方法需要传入一个ArrayList,但是这个list的类型是Object。

乍看之下好像没有问题,因为String是Object的子类,是可以进行转换的。

但是实际上代码编译出错:

Error:(18, 16) java: 不兼容的类型: java.util.ArrayList<java.lang.String>无法转换为java.util.ArrayList<java.lang.Object>

原因

上面例子的原因就是类型擦除(type erasure)。java中的泛型是在编译时做检测的。而编译后生成的二进制文件中并不保存类型相关的信息。

上面的例子中,编译之后不管是ArrayList<String> 还是ArrayList<Object> 都会变成ArrayList。其中的类型Object/String对JVM是不可见的。

但是在编译的过程中,编译器发现了两者的类型不同,然后抛出了错误。

解决办法

要解决上面的问题,我们可以使用下面的办法:

public static void actionTwo(ArrayList<?> al){
        for(Object o: al)
            log.info("{}",o);
    }

通过使用通配符?,可以匹配任何类型,从而通过编译。

但是要注意这里actionTwo方法中,因为我们不知道传入的类型到底是什么,所以我们不能在actionTwo中添加任何元素。

总结

从上面的例子我们可以看出,ArrayList<String>并不是ArrayList<Object>的子类。如果一定要找出父子关系,那么ArrayList<String>是Collection<String>的子类。

但是Object[] objArray是String[] strArr的父类。因为对Array来说,其具体的类型是已知的。

本文的例子https://github.com/ddean2009/learn-java-collections

以上就是java中的类型擦除type erasure示例详解的详细内容,更多关于java类型擦除type erasure的资料请关注脚本之家其它相关文章!

相关文章

  • Nacos 版本不一致报错Request nacos server failed解决

    Nacos 版本不一致报错Request nacos server failed解决

    这篇文章主要为大家介绍了Nacos 版本不一致报错Request nacos server failed的解决方法,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-11-11
  • 基于Java 谈回调函数

    基于Java 谈回调函数

    回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所 指向的函数时,我们就说这是回调函数
    2017-05-05
  • Java获取链接上的参数三种方法举例

    Java获取链接上的参数三种方法举例

    在Java中,我们经常需要从URL链接中获取参数,下面这篇文章主要给大家介绍了关于Java如何获取链接上参数的三种方法,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2024-06-06
  • java用类加载器的5种方式读取.properties文件

    java用类加载器的5种方式读取.properties文件

    这篇文章主要介绍了java用类加载器的5种方式读取.properties文件,详细的介绍了这5种方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-11-11
  • SpringBoot整合Dubbo框架,实现RPC服务远程调用

    SpringBoot整合Dubbo框架,实现RPC服务远程调用

    Dubbo是一款高性能、轻量级的开源Java RPC框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。今天就来看下SpringBoot整合Dubbo框架的步骤
    2021-06-06
  • Mybatis-plus更新Null字段的四种方法

    Mybatis-plus更新Null字段的四种方法

    在项目开发过程中,经常会使用Mybatis-plus的updateById()方法,快速将接收道德参数或者查询结果中原本不为null的字段更新为null,这个时候使用updateById()并不能实现这个操作,不会报错,但是对应的字段并没有更新为null,所以本文介绍了Mybatis-plus更新Null字段的方法
    2025-03-03
  • Java实现级联下拉结构的示例代码

    Java实现级联下拉结构的示例代码

    在开发过程中,会遇到很多的实体需要将查出的数据处理为下拉或者级联下拉的结构,提供给前端进行展示。本文为大家介绍了java封装下拉和级联下拉的通用工具类,需要的可以参考一下
    2022-06-06
  • IDEA添加Java类注释模版的方法

    IDEA添加Java类注释模版的方法

    本篇文章主要介绍了IDEA添加Java类注释模版的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-12-12
  • Java中Lambda表达式的使用详细教程

    Java中Lambda表达式的使用详细教程

    这篇文章将通过示例为大家详细展示Java中Lambda表达式的用法,同时也会介绍Lambda的相关知识,感兴趣的小伙伴可以跟随小编一起学习一下
    2022-05-05
  • Java RabbitMQ消息队列详解常见问题

    Java RabbitMQ消息队列详解常见问题

    消息队列是最古老的中间件之一,从系统之间有通信需求开始,就自然产生了消息队列。本文告诉什么是消息队列,为什么需要消息队列,常见的消息队列有哪些,RabbitMQ的部署和使用
    2022-07-07

最新评论