IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Java泛型擦除与兼容 -> 正文阅读

[Java知识库]Java泛型擦除与兼容

java(程序员眼中的类):

import java.sql.Timestamp;
import java.util.Date;

public class TestGenerics <T extends Date> {
    T t;

    public T getT() {
        return t;
    }
    public static void main(String[] args) {
    }

    public void test() {
        final TestGenerics<Timestamp> dateSub = new TestGenerics<>();
        final Timestamp t = dateSub.getT();
    }
}

ByteCode(虚拟机眼中的类):

// class version 52.0 (52)
// access flags 0x21
// signature <T:Ljava/util/Date;>Ljava/lang/Object;
// declaration: TestGenerics<T extends java.util.Date>
public class TestGenerics {

  // compiled from: TestGenerics.java

  // access flags 0x0
  // signature TT;
  // declaration: t extends T
  Ljava/util/Date; t

  // access flags 0x1
  public <init>()V
   L0
    LINENUMBER 4 L0
    ALOAD 0
    INVOKESPECIAL java/lang/Object.<init> ()V
    RETURN
   L1
    LOCALVARIABLE this LTestGenerics; L0 L1 0
    // signature LTestGenerics<TT;>;
    // declaration: this extends TestGenerics<T>
    MAXSTACK = 1
    MAXLOCALS = 1

  // access flags 0x1
  // signature ()TT;
  // declaration: T getT()
  public getT()Ljava/util/Date;
   L0
    LINENUMBER 8 L0
    ALOAD 0
    GETFIELD TestGenerics.t : Ljava/util/Date;
    ARETURN
   L1
    LOCALVARIABLE this LTestGenerics; L0 L1 0
    // signature LTestGenerics<TT;>;
    // declaration: this extends TestGenerics<T>
    MAXSTACK = 1
    MAXLOCALS = 1

  // access flags 0x9
  public static main([Ljava/lang/String;)V
   L0
    LINENUMBER 11 L0
    RETURN
   L1
    LOCALVARIABLE args [Ljava/lang/String; L0 L1 0
    MAXSTACK = 0
    MAXLOCALS = 1

  // access flags 0x1
  public test()V
   L0
    LINENUMBER 14 L0
    NEW TestGenerics
    DUP
    INVOKESPECIAL TestGenerics.<init> ()V
    ASTORE 1
   L1
    LINENUMBER 15 L1
    ALOAD 1
    INVOKEVIRTUAL TestGenerics.getT ()Ljava/util/Date;
    CHECKCAST java/sql/Timestamp
    ASTORE 2
   L2
    LINENUMBER 16 L2
    RETURN
   L3
    LOCALVARIABLE this LTestGenerics; L0 L3 0
    // signature LTestGenerics<TT;>;
    // declaration: this extends TestGenerics<T>
    LOCALVARIABLE dateSub LTestGenerics; L1 L3 1
    // signature LTestGenerics<Ljava/sql/Timestamp;>;
    // declaration: dateSub extends TestGenerics<java.sql.Timestamp>
    LOCALVARIABLE t Ljava/sql/Timestamp; L2 L3 2
    MAXSTACK = 2
    MAXLOCALS = 3
}

1.虚拟机眼中没有泛型, 只有一个类TestGenerics (这就是兼容旧版本)
所以java的泛型是伪泛型, 是一个非运行期现象
2. 这里, 编译器把类中用到限定类型的地方做了向上转型, 这里是转为了Date
就是擦除了泛型, 把类结构变成非泛型类也就是虚拟机认识的样子
3. 再看CHECKCAST java/sql/Timestamp, 说明编译器根据传入的具体类型, 再使用到泛型的地方, 加了一条指令, 即检验并强制向左侧类型强转
4. 左侧类型如果乱写呢, 如何检查出来: signature/declaration是编译器记下的左右两侧的信息
// signature LTestGenerics<Ljava/sql/Timestamp;>;
// declaration: dateSub extends
补充
5. 擦除的时候, 不是说向上转型, 比如 T extends A & B …多个
那就擦成A. 此时泛型类定义的那些调用了T.方法的地方, 只要不是A的方法, 也会有强转,调用的是B方法就会强转成B再调用
6. 所以擦除后需要在泛型类中强转(擦除后类没那个方法), 也需要在调用的地方强转(因为方法返回值也被擦了). 前者意味着泛型类
7. 为什么不能数组泛型, 想象下有一泛型类中有两个成员, 以及getter
假设T是Date
List t …;
t[] a …;
泛型擦除后, List本身也是泛型, 也要擦除, 擦为List, 兼容旧版本:
即List t; 还是List, 对于虚拟机来说, getT() 都不用转. 等到你getT().get(0)再转也不迟
a 为Object[]; getA 编译器想要返回 Date[], 不可能的, 因为擦除后, 相当于直接声明了一个Object[], 和随意申明了Object[]然后再想强转成Date[], 这虚拟机是不允许的.虽然有一些写法可以规避, 但是不推荐. 因为有坑, 编译器也提示不了你
所以差别的在于, 包装泛型的数据结构, List是一个类, 隐去泛型之后就是一个List, 擦除后声明的是List再转List虚拟机无所谓. 数组并不是一个类, 编译器擦成Object, 声明了一个标记为Object的对象, 已经无法强转回来了.因为声明和想转的已兼容

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-04-28 11:39:48  更:2022-04-28 11:40:45 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 2:55:44-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码