Java type erasure - why can I see the type when I look at the bytecode?

蓝咒 提交于 2021-02-07 07:35:18

问题


I am trying to understand why writing both methods in a class is not allowed

 public bool plus(List<String>) {return true;}
 public bool plus(List<Integer>) {return true;}

I try to figure how it is related to type erasure but when I decompile the following code

public class Test<T> {

   boolean plus2(List<T> ss) {return false;}
   boolean plus(List<String> ss) {return false;}
   boolean plus(Set<Integer> ss) {return false;}
}

I get the same when I decompile it with Java decompiler (jd)

Even when I print the byte code I can clearly see the types.
(Looking at SO answer that declares 'but rest assure the types are erased in the bytecode' )

    Compiled from "Test.java"
    public class com.example.Test<T> {
    public com.example.Test();
            Code:
            0: aload_0
            1: invokespecial #1                  // Method java/lang/Object."<init>":()V
            4: return

            boolean plus2(java.util.List<T>);
            Code:
            0: iconst_0
            1: ireturn

            boolean plus(java.util.List<java.lang.String>);
            Code:
            0: iconst_0
            1: ireturn

            boolean plus(java.util.Set<java.lang.Integer>);
            Code:
            0: iconst_0
            1: ireturn
            }

回答1:


Your compiler needs to be able to check the generic type information based on information in the byte code.

Java 5.0+ records the generic information in byte code, but it doesn't record it in the object instance.

e.g. there is no way to get the generic type of this List

 // list.getClass() is just ArrayList which doesn't record the generic type.
List list = new ArrayList<String>();

however this does

// list.getClass() is not ArrayList
// list is an instance of a class which extends ArrayList<String>
List list = new ArrayList<String>() { };

ParameterizedType t = (ParameterizedType) list.getClass().getGenericSuperclass();
assert t.getRawType() == ArrayList.class;
assert t.getActualTypeArguments()[0] == String.class;

This is because the byte code of the sub-class of ArrayList records the generic used in it's parent.

Note: this also works for fields, constructor/method arguments as return types and the actual type is recorded in the byte code.

However, none of these mean the generic type of an instance is available (though the generic type of a parent class/interface could be available if recorded in byte code.



来源:https://stackoverflow.com/questions/36058227/java-type-erasure-why-can-i-see-the-type-when-i-look-at-the-bytecode

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!