【发布时间】:2019-10-15 11:41:47
【问题描述】:
这是关于在 Java 中使用参数化类型的签名方法的另一个问题。
假设你有以下两种方法:
static void f(List<Integer> l) {}
static void f(List<String> l) {}
编译器会抱怨两种方法在类型擦除后具有相同的签名(两种参数类型都被擦除为 List)。
stackoverflow 上的许多类似问题都问为什么会这样,但问题总是与实例(非静态)方法有关(例如,参见 Method has the same erasure as another method in type)。
通常一半的答案基于以下(非常错误的)论点:编译器会删除字节码中的所有类型参数并使方法无法区分。好的,只需使用javap 打印字节码,您就会看到是否所有内容都被删除了! (虽然字节码丢失了很多参数化数据,但实际上保留了完整的方法签名,当您想使用包含泛型类和方法的依赖项编译新类时,这绝对有用)。
另一方面,最佳答案通常引用 JLS 8.4.2 并解释说,为了与旧的、预泛型的 Java 版本(以及较新版本中的原始类型)兼容,禁止使用具有覆盖等效签名的方法。
我对后一个参数没意见,除了它只意味着实例方法(非静态),因为静态方法无论如何都不能被覆盖。
对于静态方法可能有类似的解释,但我无法确定它。有人可以帮我理解这一点吗?
【问题讨论】:
-
关于编译器执行类型擦除的答案没有任何“非常错误”的地方。这只是一个有据可查的事实,
static与实例方法无关;正确地说,方法签名信息也根本不是字节码的一部分。 -
@user207421 我想你误读了我。我不怀疑类型擦除。例如,您无法在运行时获得关于类型参数的任何信息,这是公然的。我只是说很多人在说字节码不包含泛型时误解了类型擦除。这是错误的。顺便说一句,您是否尝试过在泛型类上运行命令
javap?也许你会感到惊讶...... -
啊,顺便说一下,来自JVM规范:docs.oracle.com/javase/specs/jvms/se13/html/…
标签: java generics types jvm javac