首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在类型删除之后,有什么方法可以查看我的代码是什么样子的吗?

在类型删除之后,有什么方法可以查看我的代码是什么样子的吗?
EN

Stack Overflow用户
提问于 2021-06-08 23:20:51
回答 4查看 185关注 0票数 4

我想知道在类型擦除之后可以使用什么工具来查看代码。例如,在类型擦除之后,我想看看下面的代码是什么样子的。我知道在最终编译之前会删除泛型类型信息,用对象或边界类型替换类型引用,创建桥方法等等。我希望在擦除过程发生后看到源代码。

代码语言:javascript
复制
  public static void main(String[] args) {
    Predicate<Object> objPredicate = (Object c) -> c.toString().length() > 2 ;
    Predicate<? super Integer> predicate = objPredicate;
    Number n = Integer.valueOf(22);
    System.out.println(predicate.test(n)); //this line does not compile
  }

如果需要编译代码才能在示例中看到擦除检查工具的工作,则可以省略非编译行或将n转换为Integer

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2021-06-09 14:41:26

在github上,我找到了基于java的开源gui工具字节码查看器,它完成了如下工作:

代码语言:javascript
复制
 public static void main(String[] var0) {
      Predicate var1 = (var0x) -> {
         return var0x.toString().length() > 2;
      };
      Integer var3 = 22;
      System.out.println(var1.test(var3));
   }

为此,我将视图菜单设置为Pane 2/Fern花/Java。

票数 0
EN

Stack Overflow用户

发布于 2021-06-08 23:55:38

我知道,泛型类型信息在最终编译之前就被删除了。

这并不完全正确,因为擦除是编译过程本身的一部分,而不是编译之前发生的事情。也就是说,擦除并不是发生在源代码上的转换。

因此,没有办法(据我所知)以编程方式获得源代码的转换版本,但通过遵循JLS 4.6中的规则,我们可以了解这样的简单示例会发生什么。

类型擦除是从类型(可能包括参数化类型和类型变量)到类型(从来不是参数化类型或类型变量)的映射。对于类型T的擦除,我们编写了_~_

  • 参数化类型(§4.5) G的擦除值是{x}。
  • 嵌套类型T.C的擦除值是{##**$$}}。
  • 数组类型T[]的擦除值是{##**$$}}。
  • 类型变量(§4.4)的擦除是其最左界的擦除。
  • 其他类型的擦除是类型本身。

类型擦除还将构造函数或方法的签名(§8.4.2)映射到没有参数化类型或类型变量的签名。构造函数或方法签名s的擦除是由与s相同的名称和s中给出的所有形式参数类型的擦除组成的签名。

如果删除方法或构造函数的签名,则方法的返回类型(§8.4.5)和泛型方法或构造函数的类型参数(§8.4.4,§8.8.4)也会被擦除。

删除泛型方法的签名没有类型参数。

对于我们得到的代码片段(忽略琐碎的擦除):

代码语言:javascript
复制
Predicate<Object> -> Predicate
Predicate<? super Integer> -> Predicate

屈服:

代码语言:javascript
复制
public static void main(String[] args) {
    Predicate objPredicate = (Object c) -> c.toString().length() > 2 ;
    Predicate predicate = objPredicate;
    Number n = Integer.valueOf(22);
    System.out.println(predicate.test(n)); //this line does not compile
}

此外,Predicate::test方法的擦除签名是:

代码语言:javascript
复制
boolean test​(Object t)
票数 3
EN

Stack Overflow用户

发布于 2021-06-09 01:12:58

如果您有一个非常简单的类型,如:

代码语言:javascript
复制
public static void main(String[] args) {
    Predicate<? super Integer> predicate = x -> x > 1;
}

它是用invokedynamic编译的,比如:

代码语言:javascript
复制
invokedynamic #7,  0  // InvokeDynamic #0:test:()Ljava/util/function/Predicate;

如果您查看BootstrapMethodsMethodType保存(几乎)所有的泛型信息(我不认为它能够保留存在通配符的事实):

代码语言:javascript
复制
#41 (Ljava/lang/Integer;)Z

它读为“接受一个整数,返回一个布尔值”。因此,从理论上讲,可以重新构建通用信息。我尝试过Intellij.class文件中重构类型--而且它不保留泛型类型。我不知道有什么工具能做到这一点。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67895684

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档