在 Java 中,重载在参数类型或参数数量上必须不同,但不能擦除,这是真的吗?

Is it true that overloading must differ in parameter types or number of parameters but not erasure in Java?

提问人:banan3'14 提问时间:10/22/2023 最后编辑:banan3'14 更新时间:10/22/2023 访问量:68

问:

擦除是在运行时决定的,要调用的重载方法在编译时解析

在 Java 中,重载必须在参数类型或参数数量上有所不同,但不能擦除,这是否正确?在重载的上下文中它不是等价的吗?如果方法在参数的类型或数量上不同,那么它们的擦除每次也会有所不同?仅仅因为重载指的是运行时而不是编译时,就说重载在擦除中必须有所不同,这是不正确的吗?

编辑:例如,具有相同的擦除和不同的参数类型,对吗?但是编译它们会导致错误foo(List<String>)foo(List<Integer>)

java:名称冲突:并具有相同的擦除foo(java.util.List<java.lang.Integer>)foo(java.util.List<java.lang.String>)

那么什么更重要呢?擦除还是参数类型?

Java 重载 类型擦除

评论

5赞 Jon Skeet 10/22/2023
“擦除是在运行时决定的”——不,不是。类型的擦除在编译时是已知的。您提供的链接实际上是在说“在执行时,类型信息已从对象中删除”。换句话说,如果你只是对一个对象的引用,你就无法分辨 a 和 a 之间的区别。List<String>List<Object>
0赞 banan3'14 10/22/2023
@JonSkeet我不知道。我认为将其包含在答案中是件好事
2赞 Sweeper 10/22/2023
请参阅 JLS 的这一部分。 并且根据定义是 的“重载”。它不编译的事实是因为在其他地方指定的规则。foo(List<String>)foo(List<Integer>)foo
0赞 Sweeper 10/22/2023
另请注意,第一个链接中的问题声称要编译的代码实际上并没有编译。Java 版本之间可能发生了一些变化。
2赞 Stephen C 10/22/2023
@Sweeper - 正确。请参阅 stackoverflow.com/a/7233730/139985,其中指出它(错误地)编译而没有错误,这是由于编译器中的错误,该错误已在 Java 7 中修复。javac

答:

2赞 banan3'14 10/22/2023 #1

擦除是在运行时决定的

不,不是。类型的擦除在编译时是已知的。您提供的链接实际上是在说“在执行时,类型信息已从对象中删除”。换句话说,如果你只是对一个对象的引用,你就无法分辨 a 和 a 之间的区别。List<String>List<Integer>

JLS的重载部分

如果一个类的两个方法(无论是在同一个类中声明的,还是都由一个类继承的,或者一个声明的和一个继承的)具有相同的名称,但签名不是覆盖等效的,则称该方法名称为重载。

这一事实不会造成任何困难,而且其本身也不会导致编译时错误。

签名在 JLS 的另一部分中定义

如果两个方法或构造函数 M 和 N 具有相同的名称、相同的类型参数(如果有)(§8.4.4),并且在将 N 的形式参数类型适应 M 的类型参数后,它们具有相同的形式参数类型,则它们具有相同的签名。

因此,由于方法签名由方法名称和参数列表组成,因此在重载的情况下,重载是具有不同形式参数类型的同名方法。

foo(List<String>)并且是上述定义的重载。它不编译的事实是由于另一节中指定的规则。foo(List<Integer>)foo

总之,定义方法是否重载的不是擦除,而是参数列表。


感谢 @Jon Skeet 和 @Sweeper 提供宝贵的意见和参考。答案主要是他们的评论和参考文献的结合