Java Generics Type Erasure byte code

前端 未结 4 1312
情话喂你
情话喂你 2021-01-04 06:32

As per the java documentation on Erasure of Generic Types,

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

publ         


        
相关标签:
4条回答
  • 2021-01-04 07:19

    The fact that the class is generic is retained. For instance, at runtime you can call

    Node.class.getTypeParameters()
    

    The next bit of code will return "T".

    (new Node<Integer>()).getClass().getTypeParameters()[0].getName()
    

    You can't get the value of type parameters at runtime, but the JVM knows they're there.

    Erasure comes into play when you construct a instance.

    Node<Integer> node = new Node<Integer>(1, null);
    Integer i = node.getData();
    

    Becomes

    Node node = new Node(1, null);
    Integer i = (Integer)node.getData();
    

    Generic classes are always generic. But instances do not carry generic type information inside them. The compiler verifies that everything you've done agrees with the generic type and then inserts casts.

    0 讨论(0)
  • 2021-01-04 07:25

    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.

    0 讨论(0)
  • 2021-01-04 07:25

    Generic type information is still saved in the bytecode, specifically in the signature information of the class members.

    For example, executing javap -verbose Node.class yields:

     ...
     LocalVariableTypeTable:
          Start  Length  Slot  Name   Signature
              0       5     0  this   Ltest/Node<TT;>;
    

    See this section from the JVM specification:

    Signatures encode declarations written in the Java programming language that use types outside the type system of the Java Virtual Machine. They support reflection and debugging, as well as compilation when only class files are available.

    A Java compiler must emit a signature for any class, interface, constructor, method, or field whose declaration uses type variables or parameterized types. Specifically, a Java compiler must emit:

    • A class signature for any class or interface declaration which is either generic, or has a parameterized type as a superclass or superinterface, or both.

    • A method signature for any method or constructor declaration which is either generic, or has a type variable or parameterized type as the return type or a formal parameter type, or has a type variable in a throws clause, or any combination thereof.

    0 讨论(0)
  • 2021-01-04 07:31

    Everyone,

    I hope it is the decompiler issue only i.e. JD-GUI.

    When I opened with different decompiler i.e. JDecompiler, I can able to see the expected Bytecode as follows:

    public class Node {
    
                private Object data;
                private Node next;
    
                public Node(Object obj, Node node) {
    /*   7*/        data = obj;
    /*   8*/        next = node;
                }
    
                public Object getData() {
    /*  12*/        return data;
                }
    }
    
    0 讨论(0)
提交回复
热议问题