java泛型之类型擦除-什么是类型擦除?
177
2023-02-08 10:04:08
Java中的泛型基本上都是在编译器这个层次来实现的。在生成的字节代码中是不包含泛型中的类型信息的。使用泛型的时候加上的类型参数,会被编译器在编译的时候去掉。这个过程就称为类型擦除。
如在代码中定义的 List和 List等类型,在编译之后都会变成 List。 JVM 看到的只是 List,而由泛型附加的类型信息对 JVM 来说是不可见的。
类型擦除的基本过程也比较简单,首先是找到用来替换类型参数的具体类。这个具体类一般是 Object。如果指定了类型参数的上界的话,则使用这个上界。把代码中的类型参数都替换成具体的类。
Tips: (Java泛型_上界extends_下界super)
1.概念
泛型的代码只存在于编译阶段,在进入JVM之前,与泛型相关的信息会被擦除掉,我们称之为类型擦除
2.示例
(1)无限制类型擦除
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)有限制类型擦除
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)擦除方法中类型定义的参数
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)桥接方法
/** * 泛型接口 * @param <T> */ public interface Info <T>{ T info(T t); }
public class InfoImpl implements Info<Integer>{ @Override public Integer info(Integer value) { return value; } }
原文链接: https://www.yukx.com/hangshuo/article/details/2366.html 优科学习网java泛型之类型擦除-什么是类型擦除?
推荐文章
-
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当时面试官笑笑说