问题描述
根据关于的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,那么字节代码不得包含如上所示的通用信息。请澄清我。
注意:我使用作为反编译器来分析字节码
解决方案关于代码本身的信息,比如泛型(或者变量名) - 这并不意味着它可以被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泛型类型擦除字节码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!