java泛型-类型擦除

深入解析Java泛型与类型擦除机制 本文深入探讨了Java泛型编程中的核心概念——类型擦除。通过解释类型擦除的原因、影响以及如何应对,我们揭示了泛型代码在运行时的实际行为。同时,文章还介绍了通配符的使用,以及如何利用相关技巧来规避类型擦除带来的挑战。理解类型擦除对于确保泛型代码的安全性和性能至关重要。 阅读详情


1.泛型和类型擦除

泛型:泛型是java 5中引入的一个新特性,允许我们在定义类和接口的时候使用类型参数,类型参数在使用时用具体的类型替换,所以为了兼容java 5之前的版本,引入了类型擦除
类型擦除:编译器在编译时擦除了所有跟类型参数相关的信息,所以在运行时访问不到类型参数相关的信息,编译器在编译时会将类型参数转换为原始类型,目的就是为了兼容java 5之前的版本,类型擦除主要的过程是首先移除所有类型参数,然后用其最顶级的父类型替换

2.变量类型擦除

2.1 无限制类型擦除

编译器在编译时将类型参数T替换为了Object,所以在运行时我们打印成员变量t的类型时访问到的是Object类型

import java.lang.reflect.Field;

public class Test01 {
    public static void main(String[] args) {
        // 无限制类型擦除
        Class<A> a = A.class;
        Field[] fields = a.getDeclaredFields();
        for (Field field : fields) {
            System.out.println(field.getName()+":"+field.getType().getSimpleName()); // t:Object
        }
    }
}

class A<T> {
    T t;
}

2.2 有限制类型擦除

编译器在编译时将类型参数T替换为了Number(由于T extends Number,所以T的上限是Number,所以T最顶级的父类型是Number),所以在运行时我们打印成员变量t的类型时访问到的是Number类型

import java.lang.reflect.Field;

public class Test02 {
    public static void main(String[] args) {
        // 有限制类型擦除
        Class<B> b = B.class;
        Field[] fields = b.getDeclaredFields();
        for (Field field : fields) {
            System.out.println(field.getName()+":"+field.getType().getSimpleName()); // t:Number
        }
    }
}

class B<T extends Number> {
    T t;
}

3.方法类型擦除

3.1 无限制类型擦除

编译器在编译时将类型参数K替换为了Object,所以在运行时我们打印成员方法fun的返回值类型时访问到的是Object类型

import java.lang.reflect.Method;

public class Test03 {
    public static void main(String[] args) {
        // 无限制类型擦除
        Class<C> c = C.class;
        Method[] methods = c.getDeclaredMethods();
        for (Method method : methods) {
            System.out.println(method.getName()+":"+method.getReturnType().getSimpleName()); // fun:Object
        }
    }
}

class C<T extends Number> {
    T t;

    public <K> K fun(K k) {
        return null;
    }
}

3.2 有限制类型擦除

编译器在编译时将类型参数K替换为了Number(由于K extends Number,所以K的上限是Number,所以K最顶级的父类型是Number),所以在运行时我们打印成员方法fun的返回值类型时访问到的是Number类型

import java.lang.reflect.Method;

public class Test04 {
    public static void main(String[] args) {
        // 有限制类型擦除
        Class<D> d = D.class;
        Method[] methods = d.getDeclaredMethods();
        for (Method method : methods) {
            System.out.println(method.getName()+":"+method.getReturnType().getSimpleName()); // fun:Number
        }
    }
}

class D<T extends Number> {
    T t;

    public <K extends Number> K fun(K k) {
        return null;
    }
}

3.3 桥接方法

首先我们来分析以下代码,左边定义了Info接口和对应的实现类,实现类指定泛型具体类型为Integer并且重写了抽象方法info,右边当编译器编译时执行类型擦除后Info接口中的类型参数T被替换成了Object类型,这时我们会发现Info接口中的抽象方法info的参数类型和返回值类型均为Object,对应的实现类中的方法info的参数类型和返回值类型均为Integer,我们都知道重写必须满足参数列表相同,但是此时不满足,所以就有了桥接方法的出现,通过桥接方法保持接口和类的实现关系
在这里插入图片描述

在理解完上图中的代码逻辑后,相信大家能看懂下面这段代码的执行结果(先打印fun:Integer,后打印fun:Object)

import java.lang.reflect.Method;

public class Test05 {
    public static void main(String[] args) {
        Class<IImpl> ii = IImpl.class;
        Method[] methods = ii.getDeclaredMethods();
        for (Method method : methods) {
            // fun:Integer
            // fun:Object
            System.out.println(method.getName()+":"+method.getReturnType().getSimpleName());
        }
    }
}

interface I<T> {
    T fun();
}

class IImpl implements I<Integer> {
    @Override
    public Integer fun() {
        return null;
    }
}
Java泛型原理篇: 类型擦除以及桥接方法 文章开始之前首先还是先思考一个经典问题 List<String> stringList = new ArrayList<>(); List<Intege. 阅读详情

相关推荐

Java中的泛型与类型擦除

特性优点缺点泛型类型安全、代码重用、简化代码类型擦除导致运行时信息丢失、某些操作受限类型擦除兼容性(与旧版Java代码兼容)、实现简单运行时无法获取泛型类型信息、灵活性受限Java泛型与类型擦除是Java语言中的重要特性,它们为开发者提供了类型安全和代码重用的能力,但同时也带来了一些限制和挑战。通过深入理解泛型与类型擦除的工作原理,并掌握实用的解决技巧,我们可以更好地利用Java泛型来编写高效、安全的代码。

shejizuopin的博客 837

【Java】 泛型擦除

1. 泛型擦除的介绍 1.1 泛型擦除的原因 1.2 泛型擦除规则 1.3 泛型擦除规则的验证 2. 通过反射获取被擦除的泛型信息 3. 使用匿名内部类解决泛型擦除导致的问题 4. 泛型擦除在Flink中的坑 4.1 算子实参有时用Lambda表达式代替匿名内部类会报错 4.2 new OutputTag(){}

渐渐的忘记,赶不上明天(读研ing,2024年毕业) 1万+

java 泛型原理 类型擦除

1.Java泛型的实现方法:类型擦除 大家都知道,Java的泛型是伪泛型,这是因为Java在编译期间,所有的泛型信息都会被擦掉,正确理解泛型概念的首要前提是理解类型擦除。Java的泛型基本上都是在编译器这个层次上实现的,在生成的字节码中是不包含泛型中的类型信息的,使用泛型的时候加上类型参数,在编译器编译的时候会去掉,这个过程成为类型擦除。 如在代码中定义List<Object>和L...

sowhat 3万+

Java 泛型:泛型和类型擦除详解-修改中...

Java 泛型的实现是在编译层,编译后生成的字节码中不包含泛型中的类型信息。所以使用泛型时,加上的类型参数,会在编译器编译的时候去掉,这个过程称为类型擦除。System.out.println("两者相同吗?System.out.println("list1集合:"+list1.getClass());System.out.println("list2集合:"+list2.getClass());}}存放 String 和 Integer 类型 list 的集合,原始类型均为。

swadian2008的博客 4379

Java泛型:类型擦除

Java的泛型类型不能用于new构建对象(也不能用于初始化数组).泛型不能用于显性地引用运行时类型的操作之中,例如转型,instanceof和new操作(包括new一个对象,new一个数组),因为所有关于参数的类型信息都在运行时丢失了,所以任何在运行时需要获取类型信息的操作都无法进行工作。原始类型就是擦除去了泛型信息,最后在字节码中的类型变量的真正类型,无论何时定义一个泛型,相应的原始类型都会被自动提供,类型变量擦除,并使用其限定类型(无限定的变量用Object)替换。一个 是List泛型类型的,...

流楚丶格念的博客 3877

MC33PT2000控制详解一:PT2000 Dev Studio工具的使用

MC33PT2000共可控制6个高低端(如控制6个高压喷油器),1个高低端(如控制高压油泵)和DC-DC模块(如升压到65V).

m0_69929716的博客 1357

Java泛型类型擦除以及类型擦除带来的问题

目录 1.Java泛型的实现方法:类型擦除 1-2.通过两个例子证明Java类型的类型擦除 2.类型擦除后保留的原始类型 3.类型擦除引起的问题及解决方法 3-1.先检查,再编译以及编译的对象和引用传递问题 3-2.自动类型转换 3-3.类型擦除与多态的冲突和解决方法 3-4.泛型类型变量不能是基本数据类型 3-5.运行时类型查询 3-6.泛型在静态方法和静态类...

u011679955的博客 1323

inferCNV包安装问题及解决办法

InferCNV是一个由broad研究所开发的,利用单细胞转录组数据分析肿瘤细胞拷贝数变异(CNV)的工具。基本思路是在整个基因组范围内,通过计算肿瘤细胞关于参考的“正常”细胞的相对表达,利用滑窗思想对邻近的基因相对表达,计算拷贝数。 先贴一个官方安装说明: 官方infercnv安装说明 安装infercnv包: if (!requireNamespace("BiocManager", quietly = TRUE)) install.packages("BiocManager") BiocManager:

m0_51042606的博客 6803

Java基础篇:泛型与类型擦除

一、什么是泛型; 泛型的本质是 参数化类型,也就是说 将所操作的数据类型 指定为一个参数,在不创建新的类型的情况下,通过泛型指定的不同类型,来控制形参具体限制的类型。类似于方法中的变量参数,此时类型也定义成参数形式,然后在使用的过程中,指定具体的类型。 这种参数类型可以在类、接口、方法中使用,分别称为泛型类、泛型接口、泛型方法。 二、泛型的好处: 没有泛型的情况的下,通过对类型Obj...

张维鹏的博客 1万+

二维码扫描与页面跳转的完整流程解析

本文详细解析了二维码扫描与页面跳转的完整流程,从核心原理到前后端实现,涵盖了二维码生成、扫码事件处理、后端验证机制及跳转逻辑等关键环节。特别介绍了如何使用qrcode.js生成二维码、WebSocket处理扫码状态以及JWT令牌验证设计,帮助开发者构建安全高效的扫码跳转系统。

cicd6pipeline的博客 1089

告别手动标注!用ENVI Classic高效搞定高光谱图像语义分割标签(以农业/地物分类为例)

本文详细介绍了如何利用ENVI Classic实现高光谱图像的半自动化智能标注,特别针对农业和地物分类场景。通过光谱特征分析、智能标注技巧和MAT文件转换,显著提升标注效率和质量,助力AI模型训练。

weixin_28694169的博客 251

Java 泛型,你了解类型擦除吗?

泛型,一个孤独的守门者。 大家可能会有疑问,我为什么叫做泛型是一个守门者。这其实是我个人的看法而已,我的意思是说泛型没有其看起来那么深不可测,它并不神秘与神奇。泛型是 Java 中一个很小巧的概念,但同时也是一个很容易让人迷惑的知识点,它让人迷惑的地方在于它的许多表现有点违反直觉。文章开始的地方,先给大家奉上一道经典的测试题。List&lt;String&gt; l1 = new ArrayList&lt;Stri

frank 的专栏 10万+

基于TIA博途的一阶滞后滤波+中位值滤波+堆栈平均值滤波算法SCL语言程序(封装FB库)

基于TIA博途的一阶滞后滤波+中位值滤波+堆栈平均值滤波算法SCL语言程序(封装FB库)

Robot_PLC_HMI_Automation 2178

Java 泛型的本质——类型擦除

泛型总共干了4件事: 编译之前编译器进行的静态分析检查(比如你不能把ArrayList<Integer>里添加string,如果做了无法编译)。 强制转换类型(比如你从ArrayList<Integer>里取一个元素时,编译器隐式地在字节码里添加一句强制转换类型,转换为int)。 在字节码中,用类型参数的限定(如果没有就是Object)来替换所有类型参数(保留上界)。这就是类型擦除。 在继承使用了类型参数的方法时(形参或者返回值的类型是T),用桥方法来保持多态。

anlian523的博客 4657

下载和运行GitHub上的代码教程总结

从昨天开始就想着从GitHub上下载一个开源的Vue的实战项目,希望能从中学习更多的Vue的实用内容,结果搞了半天好不容易下载了,不知道怎么弄。然而,今天终于成功了,激动地我赶紧来记录一下。 如何从GitHub上下载自己需要的项目: 1.首先,你要有一个自己的GitHub(https://github.com/)的账号。关于如何注册GitHub的账号以及如何获取你的SSH密钥这个问题,请大家参...

不怕万人阻挡,只怕自己投降 29万+

SAP 针对不同行业(制造业、零售业、金融业)推出了专属的云解决方案,以下是各行业的核心方案与特点

SAP推出行业专属云解决方案:制造业(SAP Digital Manufacturing Cloud)提供AI排产与质量预警,降低缺陷率;零售业(S/4HANA Cloud零售版)实现AI预测补货与全渠道库存同步,减少浪费;金融业(Business ByDesign)支持合规自动化与实时风控,降低审计成本。各方案均采用云原生架构,典型案例显示实施效果显著。

金牌架构师 493

Java 泛型——类型擦除

import java.util.*; public class t7 { public static void main(String[] args) { // TODO Auto-generated method stub List&lt;String&gt; ll = new ArrayList&lt;&gt;(); List&lt;Integer&gt; kk = ne...

Hern(宋兆恒) 9458

Aurix TC3xx系列MCU ResourceM模块配置(多核资源分配)

为减轻主核的负载率或者平衡各个核的资源分配,通常需要把一些MCU内部资源分配到从核上,在EB tresos工具中,通过ResourceM模块实现多核资源分配。

m0_38045338的博客 1388

Java中泛型——类型擦除

在程序中可以包含不同类型的Pair, 如Pair擦除类型后他们就成了原始的Pair 类型,原始类型都是Object。泛型是java1.5版本才引进的概念,在这之前没有泛型,但是,泛型代码能够很好的和之前版本的代码兼容,原因是泛型只存在代码编译阶段,在进入JVM 之前,泛型相关的信息会被擦除掉,我们称之为类型擦除。原始类型就是擦除去了泛型信息,最后在字节码中的类型变量的真正类型,无论何时定义一个泛型,相应的原始类型都会被自动提供,类型变量擦除,并使用其限定类型(无限定的变量用Object)替换。...

Java_ttcd的博客 5648

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

Java泛型-类型擦除

Java泛型-类型擦除一、概述      Java泛型在使用过程有诸多的问题,如不存在List.class, List不能赋值给List(不可协变),奇怪的ClassCastException等。 正确的使用Java泛型需要深入的了解Java的一些概念,如协变,桥接方法,以及这篇笔记记录的类型擦除。Java泛型的处理几乎都在编译器中进行,编译器生成的bytecode是不包涵泛型信息的,泛型类型信息将在编译处理是被擦除,这个过程即类型擦除。二、编译器如何处理泛型?     通常情况下,一个编译器处理泛型有两种

caihaijiang的专栏 4万+

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

140. Java 泛型 - Java 泛型类型的擦除

摘要: Java 泛型通过类型擦除实现,在编译时移除泛型信息以确保向后兼容性。无界类型参数(如 T)擦除为 Object,有界参数(如 T extends Comparable)擦除为上界类型。类型擦除导致运行时无法获取泛型信息、禁止创建泛型数组,并通过桥接方法维持多态性。例如,List<String> 和 List<Integer> 运行时均为 List,而子类覆盖泛型方法时会生成桥接方法(如 Object getValue() 调用 String getValue())。理解类型

yaoxin521123的博客 1174

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

Java泛型(类型擦除)

Java泛型类型擦除

weixin_44298385的博客 3278

Java 泛型与类型擦除

本文探讨了为什么 Java 不能实现真正意义上的泛型,并解释类型擦除的原理及其背后的原因。

专注Java和MySQL领域知识分享 1271

Java泛型类型擦除

文章目录1. 什么是类型擦除2. 什么是原始类型3. 类型擦除带来的问题和解决方法3.1 和多态的冲突3.2 不能使用`instanceof`3.3 在静态类和静态方法中的问题 1. 什么是类型擦除 Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。 Java的泛型是伪泛型,Java的泛型基本上都是在编译器这个层次上实现的,在生成的字节码中是不包

逍遥大俠 1603
上一篇: python异步aioredis
下一篇: 1.Java设计模式-创建型模式
Bigger K
博客等级 码龄7年 172粉丝 13原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值