登录 |  注册
首页 >  面试合集 >  Java大厂面经-复习笔记-更新中 >  java泛型之类型擦除-什么是类型擦除?

java泛型之类型擦除-什么是类型擦除?

Java中的泛型基本上都是在编译器这个层次来实现的。在生成的字节代码中是不包含泛型中的类型信息的。使用泛型的时候加上的类型参数,会被编译器在编译的时候去掉。这个过程就称为类型擦除。

如在代码中定义的 List和 List等类型,在编译之后都会变成 List。 JVM 看到的只是 List,而由泛型附加的类型信息对 JVM 来说是不可见的。

类型擦除的基本过程也比较简单,首先是找到用来替换类型参数的具体类。这个具体类一般是 Object。如果指定了类型参数的上界的话,则使用这个上界。把代码中的类型参数都替换成具体的类。

Tips: (Java泛型_上界extends_下界super)

1.概念

泛型的代码只存在于编译阶段,在进入JVM之前,与泛型相关的信息会被擦除掉,我们称之为类型擦除

2.示例

(1)无限制类型擦除

类型擦除.png

public class Erasure<T> {
 
    private T key;
 
    public T getKey() {
        return key;
    }
 
    public void setKey(T key) {
        this.key = key;
    }
}


import java.lang.reflect.Field;
 
public class Demo {
    public static void main(String[] args) {
 
        Erasure<Integer> erasure = new Erasure<>();
        // 利用反射获取类的字节码文件的Class类对象
        Class<? extends Erasure>  clz = erasure.getClass();
        // 获取所有的成员变量
        Field[] declaredFields = clz.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            // 打印成员变量的名称和类型
            System.out.println(declaredField.getName() + ":" + declaredField.getType().getSimpleName()); // key:Object
 
        }
    }
}

 (2)有限制类型擦除

类型擦除2.png

public class Erasure<T extends Number> {
 
    private T key;
 
    public T getKey() {
        return key;
    }
 
    public void setKey(T key) {
        this.key = key;
    }
}

import java.lang.reflect.Field;
 
public class Demo {
    public static void main(String[] args) {
 
        Erasure<Integer> erasure = new Erasure<>();
        // 利用反射获取类的字节码文件的Class类对象
        Class<? extends Erasure>  clz = erasure.getClass();
        // 获取所有的成员变量
        Field[] declaredFields = clz.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            // 打印成员变量的名称和类型
            System.out.println(declaredField.getName() + ":" + declaredField.getType().getSimpleName()); // key:Number
        }
    }
}

(3)擦除方法中类型定义的参数

类型擦除3.png

import java.util.List;
 
public class Erasure<T extends Number> {
 
    private T key;
 
    public T getKey() {
        return key;
    }
 
    public void setKey(T key) {
        this.key = key;
    }
 
    /**
     * 泛型方法
     * @param t
     * @param <T>
     * @return
     */
    public <T extends List> T show(T t) {
        return t;
    }
}
import java.lang.reflect.Field;
import java.lang.reflect.Method;
 
public class Demo {
    public static void main(String[] args) {
 
        Erasure<Integer> erasure = new Erasure<>();
        // 利用反射获取类的字节码文件的Class类对象
        Class<? extends Erasure>  clz = erasure.getClass();
        // 获取所有的成员变量
        Field[] declaredFields = clz.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            // 打印成员变量的名称和类型
            System.out.println(declaredField.getName() + ":" + declaredField.getType().getSimpleName()); // key:Number
 
        }
 
 
        System.out.println("---------------------------------------------------");
 
        // 获取所有的方法
        Method[] declaredMethods = clz.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            // 打印方法名和返回值类型
            System.out.println(declaredMethod.getName() + ":" + declaredMethod.getReturnType().getSimpleName());
        }
        /**
         * getKey:Number
         * show:List
         * setKey:void
         */
    }
}

(4)桥接方法

类型擦除4.png

/**
 * 泛型接口
 * @param <T>
 */
public interface Info <T>{
    T info(T t);
}
public class InfoImpl implements Info<Integer>{
    @Override
    public Integer info(Integer value) {
        return value;
    }
}
上一篇: 说一下ConcurrentHashMap为什么是线程安全?如何实现?
下一篇: kafka和RabbitMQ主要差异有哪些
推荐文章
  • Halfmessage是在消息队列(MessageQueue,MQ)领域,尤其是阿里巴巴开源的消息中间件RocketMQ中提到的一个术语,它特指一种特殊的事务消息状态。在分布式事务处理的上下文中,半消息(HalfMessage)指的是那些已被生产者成功发送到消息队列服务器,但由于生产者尚未完成本地事
  • 可靠消息服务方案是一种用于确保在分布式系统中实现消息传递最终一致性的技术方案。在分布式事务处理中,尤其是在微服务架构或者分布式系统架构下,不同服务之间需要通过异步消息通信来协调事务,而直接使用传统的ACID事务往往难以满足高并发、高性能的需求。可靠消息服务(ReliableMessageServic
  • TCC(Try-Confirm-Cancel)是一种分布式事务解决方案,该方案由分布式事务协调专家LeslieLamport提出,并在实践中逐渐演化和发展。TCC模式常用于微服务架构下的分布式事务场景,它的核心思想是在每个参与分布式事务的服务中实现三个阶段的操作:Try阶段:这个阶段是尝试阶段,服务
  • 对于Java资深工程师的面试,面试官通常会期望候选人能深入理解Java的核心概念、设计模式、框架原理、并发编程、JVM优化、以及实际项目中的最佳实践等方面的知识。以下是一些可能会被问到的资深Java面试题示例:Java基础部分Java内存模型(JMM)是如何工作的?解释Java中的内存泄漏,并给出具
  • 1、Goroutine定义 Golang在语言级别支持协程,称之为Goroutine。Golang标准库提供的所有系统调用操作(包括所有的同步I/O操作),都会出让CPU给其他Goroutine。这让Goroutine的切换管理不依赖于系统的线程和进程,也不依赖于CPU的核心数量,而是交给Golan
  • Go基础面试题1、与其他语言相比,使用Go有什么好处?与其他作为学术实验开始的语言不同,Go代码的设计是务实的。每个功能和语法决策都旨在让程序员的生活更轻松。Golang针对并发进行了优化,并且在规模上运行良好。由于单一的标准代码格式,Golang通常被认为比其他语言更具可读性。自动垃圾收集明显比J
学习大纲