使用IDEA反编译没有擦除泛型的原因解析

使用idea反编译没有擦除泛型的原因解析

 

前言

java泛型是进阶高级开发必备技能之一,了解实现泛型的基本原理,有助于写出更优质的代码。

众所周知,java是伪泛型,是通过类型擦除(type erasure)来实现的。为了“查看/证明”java对泛型类型的擦除,我们常常通过反编译的手段实现。intellij idea作为java开发主流ide,它内置的反编译功能是最为常用的反编译工具。

但是,你会发现,idea的反编译竟没有擦除泛型。

 

✍正文

如下代码:

/**
* 在此处添加备注信息
*
* @author yourbatman's home page. <a href=https://yourbatman.cn>https://yourbatman.cn</a>
* @author yourbatman. <a href=mailto:yourbatman@aliyun.com>send email to me</a>
* @author wechat:fsx641385712
* @since 0.0.1
*/
public class tester {
  @test
  public void fun() {
      list<integer> numbers = new arraylist<>();
      numbers.add(18);
      list newnumbers = numbers;
      newnumbers.add("yourbatman");
      system.out.println(numbers);
  }
  @test
  public void fun1() {
      list<integer> intlist = new arraylist<>();
      list<string> stringlist = new arraylist<>();
      system.out.println(intlist.getclass() == stringlist.getclass());
  }
}

我们借助idea的反编译后的内容:找到需要反编译的.class文件

在这里插入图片描述

双击即可查看:

在这里插入图片描述


我的天,泛型类型不应该被擦除了吗,为毛还在?idea的反编译工具难道有bug?

尝试其它反编译工具

idea最初内置的是著名的jd-gui反编译插件,从2016年起改为自研的反编译插件java bytecode decompiler,一直沿用至今:

在这里插入图片描述

为了验证此问题,我计划多试试几款反编译工具。

jd-gui

下载地址:https://github.com/java-decompiler/jd-gui/releases

在这里插入图片描述

尴尬的是,双击打不开:

在这里插入图片描述

无奈。在虚拟机里启了个windows 11来跑:

在这里插入图片描述

结论:没有擦除泛型类型。和idea不同的是它反编译出来的结果更“原始”一丢丢

jadx

下载地址:https://github.com/skylot/jadx/releases

在这里插入图片描述

同样的windows 11上运行进行反编译:

在这里插入图片描述

结论:没有擦除泛型类型。结果不说和idea差不多,也是一模一样。

jad

下载地址:https://varaneckas.com/jad

在这里插入图片描述

由于我的本是基于apple silicon芯片的,所以只能继续在windows上执行了:

在这里插入图片描述

结论:泛型类型被擦除了。

beyond compare 4

beyond compare的主业是做文件比较,其实它也可以java反编译。只需在https://www.scootersoftware.com/download.php?zz=moreformats下载所需插件:

在这里插入图片描述

使用beyond compare 4进行反编译:

在这里插入图片描述

结论:泛型类型被擦除了。beyond compare 4的反编译基于jad,因此效果和jad一模一样

javap -c

使用最底层的javap -c进行反编译:

在这里插入图片描述

结论:泛型类型被擦除了。

 

总结

有些擦除了但有些没有擦除泛型类型,到底该信谁呢?当然是无条件相信javap -c,因为一切反编译操作都基于它。so结论是:java的泛型是伪泛型,编译后泛型类型都会被擦除。

记住结论的同时,通过本文对比了多个反编译器的结果亦可得到两条基本的常识:

  • 像idea内置的java bytecode decompiler以及jadx这种比较新(还在持续迭代)的工具,称作智能反编译器更为合适:它能重排序代码,并且“保留”住泛型类型,方便开发者阅读
  • java泛型引入至今已有近20年,“伪泛型”已被认为是所有开发者的共识,没有必要再在反编译后体现出来反倒大大降低了可读性。像jad这种“上古”时期的反编译器,依旧原汁原味 推荐阅读 intellij idea 2022.3正式发布,配置云同步&支持redis好用到炸

本专栏源代码库:https://github.com/yourbatman/yourbatman-999-question

关于为啥用idea反编译没有擦除泛型的文章就介绍至此,更多相关idea反编译没有擦除泛型内容请搜索硕编程以前的文章,希望以后支持硕编程

下一节:java解决动态配置字段需求问题介绍

java编程技术

相关文章