Java类型擦除-当我查看字节码时为什么能看到类型? [英] Java type erasure - why can I see the type when I look at the bytecode?

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

问题描述

我试图理解为什么不允许在一个类中同时编写这两种方法

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;}
}

使用Java反编译器(jd)进行反编译时,我会得到相同的结果

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

即使我打印字节码,我也可以清楚地看到类型.
(请看SO answer 声明但请确保在字节码中删除了类型')

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
            }

推荐答案

您的编译器需要能够根据字节码中的信息检查通用类型信息.

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

Java 5.0+将通用信息记录为字节码,但不会将其记录在对象实例中.

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>();

但是这样做

// 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;

这是因为ArrayList子类的字节代码记录了其父级中使用的泛型.

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.

这篇关于Java类型擦除-当我查看字节码时为什么能看到类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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