Java泛型6——类型擦除

注:以下内容基于Java 8,所有代码都已在Java 8环境下测试通过

1. 什么是类型擦除

泛型是在Java 1.5被引进的,但是泛型代码可以和之前的版本兼容,原因就是泛型只存在代码编译阶段,编译后的字节码中(也就是运行时)不包含泛型中的类型信息。使用泛型时,泛型相关的类型参数信息会在编译时被擦除掉,这个过程被称为类型擦除。比如:

import java.util.LinkedList;

public class Main {
    public static void main(String[] args) {
        LinkedList<Integer> i = new LinkedList<>();
        LinkedList<String> s = new LinkedList<>();

        System.out.println("i:" + i.getClass());
        System.out.println("s:" + s.getClass());
    }
}

请添加图片描述

从运行结果可以看到,虽然为 is 指定了不同的类型参数,但在运行时它们实际上是同一种类型(都是 LinkedList )。这就是类型擦除的作用,在编译时将代码中的类型参数擦除只保留原始类型

2. 原始类型

原始类型是擦除了泛型信息后字节码中的类型,无论何时定义一个泛型类型,相应的原始类型都会被自动地提供。类型参数信息被擦除只会保留原始类型。根据是否限定类型,原始类型替换有以下两种情况:

2.1 无限定类型

将类型参数替换为Object。例如:

class Test<T> {
    private T value;

    public T getValue() {
        return value;
    }

    public void setValue(T value) {
        this.value = value;
    }
}

类型擦除后:

class Test {
    private Object value;

    public Object getValue() {
        return value;
    }

    public void setValue(Object value) {
        this.value = value;
    }
}

2.2 有限定类型

将类型参数替换为上限或下限。例如:

class Test<T extends Number> {
    private T value;

}

类型擦除后:

class Test {
    private Number value;
}

3. 类型擦除原理

Java在编译时进行泛型的类型擦除,但在进行类型擦除时会将传入的类型参数记录下来。当对被擦除后的泛型对象操作时编译器会根据记录的类型参数对其进行类型转换,将其从原始类型转换为未传入的参数类型。

4. 类型擦除带来的问题

主要有以下几点(部分问题在之前已经说过了,如泛型变量不能是基本数据类型,具体内容可参考CSDN博客):

  • 引用传递问题
  • 自动类型转换问题
  • 类型擦除与多态冲突
  • 泛型变量不能是基本数据类型
  • 运行时类型检查异常
  • 泛型异常捕获
  • 不能创建泛型类型数组
  • 不能实例化泛型类型
  • 类型擦除后的冲突
  • 不能使用静态域
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值