简介

泛型是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

本文作者:flydean程序那些事

本文链接:http://www.flydean.com/java-type-erasure/

本文来源:flydean的博客

欢迎关注我的公众号:程序那些事,更多精彩等着您!

java中的类型擦除type erasure的更多相关文章

  1. Java中泛型 类型擦除

    转自:Java中泛型是类型擦除的 Java 泛型(Generic)的引入加强了参数类型的安全性,减少了类型的转换,但有一点需要注意:Java 的泛型在编译器有效,在运行期被删除,也就是说所有泛型参数类 ...

  2. Java中的类型擦除与桥方法

    类型擦除 Java在语法中虽然存在泛型的概念,但是在虚拟机中却没有泛型的概念,虚拟机中所有的类型都是普通类.无论何时定义一个泛型类型,编译后类型会被都被自动转换成一个相应的原始类型. 比如这个类 pu ...

  3. java中的类型安全问题-Type safety: Unchecked cast from Object to ...

    首先,java语言室类型安全的,通常我们遇到这个问题是出现在Object转化为目标类型时, 这个转化并不是安全的.这个问题普遍认为因为使用了jdk1.5或者1.6的泛型, request.getAtt ...

  4. java 泛型的类型擦除与桥方法

    泛型类 --代码参考:java核心技术 卷1 第十版 public class Pair<T> { private T first; private T second; //构造器 pub ...

  5. Java泛型类与类型擦除

    转载自:http://blog.csdn.net/lonelyroamer/article/details/7868820 一.Java泛型的实现方法:类型擦除 前面已经说了,Java的泛型是伪泛型. ...

  6. java 泛型的类型擦除和桥方法

    oracle原文地址:https://docs.oracle.com/javase/tutorial/java/generics/erasure.html 在Java中,泛型的引入是为了在编译时提供强 ...

  7. c++中的类型擦除

    (原创)c++中的类型擦除 c++11 boost技术交流群:296561497,欢迎大家来交流技术. 关于类型擦除,可能很多人都不清楚,不知道类型擦除是干啥的,为什么需要类型擦除.有必要做个说明,类 ...

  8. Java泛型:类型擦除

    类型擦除 代码片段一 Class c1 = new ArrayList<Integer>().getClass(); Class c2 = new ArrayList<String& ...

  9. JAVA中值类型和引用类型的不同(面试常考)

    转载:https://www.cnblogs.com/1ming/p/5227944.html 1. JAVA中值类型和引用类型的不同? [定义] 引用类型表示你操作的数据是同一个,也就是说当你传一个 ...

  10. Java泛型之类型擦除

    类型擦除 学过C++模板的,在使用Java泛型的时候,会感觉到有点不疑问,例如:(1)无法定义一个泛型数组.无法调用泛型参数对象中对应的方法(当然,通过extends关键字是可以做到,只是比较麻烦): ...

随机推荐

  1. vscode添加gitbash终端方法

    1.打开vscode 2.点击文件,ctrl+, 3.搜索shell windows { ... // 添加如下代码 "terminal.integrated.profiles.window ...

  2. django时区相关说明

    # naive time 从字面意思上理解,这是个"幼稚的时间",所以可以理解为它是个本地时间,不带时区信息,不能直接用于存储,如下 import datetime datetim ...

  3. 在 C++ 项目中,通过源码使用 PaddlePaddle 实现 OCR 功能

    My-PaddleOCR 介绍 如何在 C++ 项目中,通过源码使用 PaddlePaddle 实现 OCR 功能. 本项目的所有源码:gitee: paddleocr 目前,官方提供使用 Paddl ...

  4. 【Azure Spring Cloud】使用azure-spring-boot-starter-storage来上传文件报错: java.net.UnknownHostException: xxxxxxxx.blob.core.windows.net: Name or service not known

    问题描述 使用 azure-spring-boot-starter-storage 来上传文件到 Storage Blob中,并把应用部署到Azure 中国区的Spring Cloud服务后,调用上传 ...

  5. Linux安装Docker教程

    介绍 Docker利用Linux核心中的资源分脱机制,例如cgroups,以及Linux核心名字空间(name space),来创建独立的软件容器(containers).可以在单一Linux实体下运 ...

  6. Prompt进阶系列1:LangGPT(从编程语言反思LLM的结构化可复用提示设计框架)

    Prompt进阶系列1:LangGPT(从编程语言反思LLM的结构化可复用提示设计框架) 大语言模型 (Large Language Models, LLMs) 在不同领域都表现出了优异的性能.然而, ...

  7. .NET Conf China 2023济南站社区活动

     2024年3月3日,在这个春暖花开的日子里,由微软MVP项目.山东财经大学管理科学与工程学院.胶东开发者社区.济南.NET俱乐部联合举办了[.NET Conf China 2023 JiNan Wa ...

  8. 使用Deployment和Service实现简单的灰度发布

    在Kubernetes中,使用单个Service和多个Deployment来实现灰度发布的一种常见方法是利用标签(Labels)和选择器(Selectors)来控制哪些Pods接收来自Service的 ...

  9. ubuntu环境下python下使用OpenCV库读取USB摄像头的画面

    一 概念 OpenCV是一个开源的计算机视觉和机器学习软件库.它可以使用pip命令行中的以下命令安装:"pip install opencv-python" 这个做视觉处理,非常的 ...

  10. Spring Boot中的Freemarker模版引擎引用css和js的正确姿势

    最近在弄个软件更新Web管理系统,项目中引用了js和css等样式,但发现iframe中无法成功引入样式,稍微研究之后成功的发现的解决方法,以及spring boot项目中正确引用css和js的正确姿势 ...