Java泛型类型擦除字节码 [英] Java Generics Type Erasure byte code

查看:116
本文介绍了Java泛型类型擦除字节码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据关于擦除泛型类型的java文档 ,

考虑以下泛型类,它表示一个单链表中的节点:$ b​​
$ b

  public class Node< T> {

私人T数据;
私人节点< T>下一个;

public Node(T data,Node< T> next)}
this.data = data;
this.next = next;
}

public T getData(){return data; }
// ...
}

因为类型参数 T 是无界的,Java编译器用 Object 替换它:

  public class节点{

私人对象数据;
下一个私人节点;

public Node(Object data,Node next){
this.data = data;
this.next = next;
}

public Object getData(){return data; }
// ...
}

但是用Java 1.7编译后.0_11,当我用任何反编译器打开它时,我可以看到与源代码相同的代码。

  public class Node< T> ; 
{
私人T数据;
私人节点< T>下一个;

public Node(T paramT,Node< T> paramNode)
{
this.data = paramT;
this.next = paramNode;
}

public T getData()
{
return this.data;






如果在编译时应用了Type-Erasure,那么字节代码不得包含如上所示的通用信息。请澄清我。



注意:我使用 JD-GUI 作为反编译器来分析字节码

解决方案

关于代码本身的信息,比如泛型(或者变量名) - 这并不意味着它可以被JVM使用。

类的反汇编字节码如下所示(你可以用 javap -c Node.class )看到它:

 公共类节点< T> {
公共节点(T,节点< T>);
代码:
0:aload_0
1:invokespecial#1 //方法java / lang / Object。< init>:()V
4:aload_0
5:aload_1
6:putfield#2 //字段数据:Ljava / lang / Object;
9:aload_0
10:aload_2
11:putfield#3 // Field next:LNode;
14:返回

public T getData();
代码:
0:aload_0
1:getfield#2 //字段数据:Ljava / lang / Object;
4:areturn
}

你可以看到方法和参数是通用的类型在那里,但由于擦除过程,代码本身就像预期的那样引用Object。


As per the java documentation on Erasure of Generic Types,

Consider the following generic class that represents a node in a singly linked list:

public class Node<T> {

    private T data;
    private Node<T> next;

    public Node(T data, Node<T> next) }
        this.data = data;
        this.next = next;
    }

    public T getData() { return data; }
    // ...
}

Because the type parameter T is unbounded, the Java compiler replaces it with Object:

public class Node {

    private Object data;
    private Node next;

    public Node(Object data, Node next) {
        this.data = data;
        this.next = next;
    }

    public Object getData() { return data; }
    // ...
}

But after compilation with Java 1.7.0_11, when I opened it with any decompiler I can see the same code as like source code.

public class Node<T>
{
  private T data;
  private Node<T> next;

  public Node(T paramT, Node<T> paramNode)
  {
    this.data = paramT;
    this.next = paramNode;
  }

  public T getData()
  {
    return this.data;
  }
}

If Type-Erasure applied at compile then the byte code must not contain Generic information as shown above. Kindly clarify me.

NOTE: I am using JD-GUI as a decompiler to analyze the byte code

解决方案

The bytecode contains meta information about the code itself, such as generic types (or variable names) - it does not mean it's useable by the JVM.

The disassembled bytecode of your class looks like below (you can see it with javap -c Node.class):

public class Node<T> {
  public Node(T, Node<T>);
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: aload_0
       5: aload_1
       6: putfield      #2                  // Field data:Ljava/lang/Object;
       9: aload_0
      10: aload_2
      11: putfield      #3                  // Field next:LNode;
      14: return

  public T getData();
    Code:
       0: aload_0
       1: getfield      #2                  // Field data:Ljava/lang/Object;
       4: areturn
}

You can see that the methods and arguments generic types are there but the code itself refers to Object as expected due to the erasure process.

这篇关于Java泛型类型擦除字节码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆