登录 |  注册
首页 >  面试合集 >  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为什么是线程安全?如何实现?
推荐文章
  • Java中的泛型基本上都是在编译器这个层次来实现的。在生成的字节代码中是不包含泛型中的类型信息的。使用泛型的时候加上的类型参数,会被编译器在编译的时候去掉。这个过程就称为类型擦除。如在代码中定义的List和List等类型,在编译之后都会变成List。JVM看到的只是List,而由泛型附加的类型信息对
  • Segment段 ConcurrentHashMap和HashMap思路是差不多的,但是因为它支持并发操作,所以要复杂一些。整个ConcurrentHashMap由一个个Segment组成,Segment代表”部分“或”一段“的意思,所以很多地方都会将其描述为分段锁。注意,行文中,我很多地方用了“槽
  • HashMap根据键的hashCode值存储数据,大多数情况下可以直接定位到它的值,因而具有很快的访问速度,但遍历顺序却是不确定的。HashMap最多只允许一条记录的键为null,允许多条记录的值为null。HashMap非线程安全,即任一时刻可以有多个线程同时写HashMap,可能会导致数据的不一
  • Map类图重点关注这几个类参考资料解析(1)HashMap:它根据键的hashCode值存储数据,大多数情况下可以直接定位到它的值,因而具有很快的访问速度,但遍历顺序却是不确定的。HashMap最多只允许一条记录的键为null,允许多条记录的值为null。HashMap非线程安全,即任一时刻可以有多
  • 题记:前几天面试Java基础给来了个面试题Integera=200,b=200;System.out.println(a==b);当时回答是false,后来面试官又来了一个Integera=100,b=100;System.out.println(a==b);这个回答的也是false当时面试官笑笑说
学习大纲