泛型代码和虚拟机

虚拟机没有泛型类型的对象–所有对象都属于普通类。

那么虚拟机怎么工作?

类型擦除、原始类型、给JVM的指令、桥方法、Java泛型转换的事实

Java泛型转换的事实:

  • 虚拟机中没有泛型,只有普通的类和方法

  • 所有的类型参数都用他们的限定类型替换

  • 桥方法被合成来保持多态

  • 为保持类型安全性,必要时插入强制类型转换

类型擦除–type erasure

Java泛型的处理在编译器中运行,编译生成的字节码bytecode不包含泛型信息,泛型信息在编译处理时被擦除(erasure),这个过程即类型擦除

原始类型(raw type)

定义一个泛型类型,编译器自动提供一个相应的原始类型(raw type),原始类型就是删除类型参数(包括泛型类型变量及其限定类型)后的泛型类型名。擦除类型变量,原始类型替换为限定类型(无限定则用Object)

泛型变量有限定类型示例: <T extends Comparable & Serializable> ,因为Comparable包含实现方法CompareTo,而Serializable只是个标签(Tagging)接口,若二者对调位置,则原始类型将用Serializable来替换,这样在编译器必要时要向Comparable插入强制类型转换,所以为了提高效率,最好将标签(Tagging)接口放在边界列表的末尾
标签(Tagging)接口:没有方法的接口

给JVM的指令:

  • 擦除方法返回类型,编译器将方法调用处理为两条JVM虚拟机指令

  • 对原始方法的调用(返回Object类型或限定类型)

  • 将返回的Object类型强制转换为泛型类型的具体类型(如Employee)

  • 补充#当存取一个泛型域时也要插入强制类型转换

如何证明被擦除了?

package com.wht.generic;

import java.util.ArrayList;

public class Test {

  public static void main(String[] args) {
    ArrayList<String> list1 = new ArrayList<String>();
    list1.add("abc");

    ArrayList<Integer> list2 = new ArrayList<Integer>();
    list2.add(123);

    System.out.println(list1.getClass() == list2.getClass());
  }


}

返回true

只不过在编译的时候,add不匹配的类型数据直接报错。

  public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
    ArrayList<Integer> list = new ArrayList<Integer>();

    list.add(1);  //这样调用 add 方法只能存储整形,因为泛型类型的实例为 Integer

    list.getClass().getMethod("add", Object.class).invoke(list, "asd");

    for (int i = 0; i < list.size(); i++) {
      System.out.println(list.get(i));
    }
  }

这个例子就说明了另外一个问题,java的泛型是假泛型,只适用于编译器的校验,运行时已经无效。

桥方法目前不做整理,后面再看

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值