java泛型字节码分析

java泛型


   从jdk1.5开始,java语言加入了泛型支持,泛型是一种编译时的约束,可以在编译阶段确定数据的类型。泛型是在 Java 平台上作为编译时转换实现的。编译器实际上生成与使用非泛型源代码时相同的字节指令,插入运行时类型转换以在每次访问时将值转换为正确的类型。尽管是相同的字节码,但是类型参数信息用 一个新的签名(signature) 属性记录在类模式中。JVM 在装载类时记录这个签名信息,并在运行时通过反射使它可用。


字节码分析

 

非泛型类

public class Box {

    private Object object;

    public void add(Object object) {

        this.object = object;
    }

    public Object get() {
        return object;

    }
}

class 字节码信息
this class :Box
super class: Object

Fileds:
<Ljava/lang/Object;>

Methods:
add : <Ljava/lang/Object;()V>
get : <()Ljava/lang/Object;>

 


泛型类

 

public class Box<T> {

    private T t; // T stands for "Type"

    public void add(T t) {
        this.t = t;
    }


    public T get() {
        return t;
    }
}


class 字节码信息


this class :Box

[0] Signature <T:<Ljava/lang/Object;><Ljava/lang/Object;>>
super class: Object


Fileds:

<Ljava/lang/Object;>
[0] Signature <TT;>

Methods:
add : <Ljava/lang/Object;()V>
[1] Signature <TT()V;>
get : <()Ljava/lang/Object;>
[1] Signature <()TT;> 

  通过查看字节码可以发现带泛型的类和不带泛型类只在Signature部分有区别。如上TT表明类使用泛型,泛型参数名称为T。

 

方法和构造函数范围泛型

 

  泛型可以在方法或构造函数范围内声明,如下所示。它只在其声明的函数范围内有效。

public <U> void inspect(U u){

        System.out.println("T: " + t.getClass().getName());
        System.out.println("U: " + u.getClass().getName());
    }


方法信息:


inspet : <Ljava/lang/Object;()V>
[1] Signature <<U:Ljava/lang/Object;>(TU)V;>

 



 限定范围类型参数

 

public <U extends Number> void inspect(U u) {

        System.out.println("T: " + t.getClass().getName());
        System.out.println("U: " + u.getClass().getName());

    }

 


方法信息:
inspet : <Ljava/lang/Number;()V>
[1] Signature <<U:Ljava/lang/Number;>(TU)V;>

还可以增加要实现的接口限制,如下:

    public <U extends Number & Serializable> void inspect(U u) {

        System.out.println("T: " + t.getClass().getName());
        System.out.println("U: " + u.getClass().getName());

    }


方法信息:
inspet : <Ljava/lang/Number;()V>
[1] Signature <<U:Ljava/lang/Number;Ljava/lang/Serializable;>(TU)V;>

 

泛型信息擦除

 

类型参数在编译的时候会被擦除,只保留不带类型参数的raw type,因此无法再运行上下文中使用泛型类型。如下面这段代码,编译时无法通过的。

public class MyClass<E> {

    public static void myMethod(Object item) {
        if (item instanceof E) {  //Compiler error
            ...
        }

        E item2 = new E();   //Compiler error
        E[] iArray = new E[10]; //Compiler error
        E obj = (E)new Object(); //Unchecked cast warning
    }

所以泛型参数只能出现在类,方法,属性的声明中。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值