java泛型探秘(二):泛型擦除

目录

一. 泛型擦除是什么

二. 为什么要擦除

三. 擦除造成的限制

1. 特殊的rawType

2. 不支持原始类型

3. 不能用占位符创建实例或数组

4. 不能创建泛型数组 


一. 泛型擦除是什么

java泛型是编译期的泛型,不是运行时的泛型

       java语言是跨平台的,每个平台都有对应的JVM(java虚拟机),编写的java源码不能直接在JVM中运行,能在JVM中运行的是字节码,一般都以.class文件格式存在,java源码文件转换成.class字节码文件的过程称为编译期,编译期会对java源码严格校验,生成合格的字节码。编译过程中,编译器遇到泛型代码(泛型类、方法的定义和使用)会进行特殊处理,主要进行检查类型安全并擦除泛型信息,编译之后生成的.class字节码不包含泛型信息(实际上会保留一些泛型信息,只有在某些特殊情况下才会使用),JVM虚拟机运行时不知道泛型的存在,也不会针对泛型做特殊处理。如下代码:

/**
  这是一个很简单的泛型化类,拥有一个属性var,和该属性的setter和getter方法
**/
public class Generic<T> {
    
    private T var;

    public T getVar() {
        return var;
    }

    public void setVar(T var) {
        this.var = var;
    }
    
    
    public static void main(String[] args) {
        
        // 设置类型为Integer
        Generic<Integer> inGeneric = new Generic<Integer>();
        
        // 设置属性值
        inGeneric.setVar(10);
        
        // 输出值
        System.out.println(inGeneric.getVar().intValue()); 
    }
}

       上面定义了泛型类Generic, 其中属性var的声明类型也是泛型修饰,并提供了var的getter和setter方法。在main方法里首先创建了Generic实例,传入类型为Integer,意味着属性var的类型是Integer,即: Generic<Integer> inGeneric = new Generic<Integer>(),并调用inGeneric.setVar(10)设置var值为10,调用inGeneric.getVar().intValue()获取var的值。上面这段示例代码虽然简单,但是在类定义、属性声明、方法入参与出参、泛型类实例创建和方法调用上都使用了,通过观察编译后的.class文件,比较能全面直观地了解泛型擦除的效果。

       使用javap -v 命令输出.class字节码内容

javap -v Generic.class

       输出结果,由于字节码内容比较多,这里只摘出部分内容:

Classfile /D:/workspace/learn-class/bin/cn/learn/classes/Generic.class
  Last modified 2019-4-8; size 1247 bytes
  MD5 checksum 917868e0a5c70d19355976a97fe8b62e
  Compiled from "Generic.java"
public class cn.learn.classes.Generic<T extends java.lang.Object> extends java.lang.Object
  minor version: 0
  major version: 51
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Class              #2             // cn/learn/classes/Generic
   #2 = Utf8               cn/learn/classes/Generic
   #3 = Class              #4             // java/lang/Object
   #4 = Utf8               java/lang/Object
   #5 = Utf8               var

   ....

   public T getVar();
    descriptor: ()Ljava/lang/Object;
    flags: ACC_PUBLIC
    S
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值