有人可以解释为什么第二个类不能编译吗?
1 使用 javac 和 JDK 6 编译良好(Eclipse 会提示这段代码)
public class SameSignatureMethods {
public <T extends String> Boolean test()
{
return true;
}
public <T extends Character> Double test()
{
return 1d;
}
}
2 对该示例稍作改动,编译失败并出现以下错误:
name clash: <T>test() and <T>test() have the same erasure
唯一的变化是方法的返回类型:
public class SameSignatureMethods {
public <T extends String> Boolean test()
{
return true;
}
public <T extends Character> Boolean test() {
return true;
}
}
这就是 first class 的 main 方法的样子:
public static void main(String[] args) {
SameSignatureMethods m = new SameSignatureMethods();
System.out.println("m.<Character>test()=" + m.<Character>test());
System.out.println("m.<String>test()=" + m.<String>test());
}
最佳答案
因此,JDK 编译器编译第一个版本而不编译第二个版本,而 Eclipse 编译器则两个版本都不编译。
从Java字节码的角度来看,第一个版本包含两种不同的方法(类型删除后),即public java.lang.Boolean test()
和 public java.lang.Double test()
,这是完全有效的。 JDK 编译器和 Eclipse 编译器有时会在您覆盖泛型方法时生成此类方法,但这些方法随后会被标记为合成桥接方法。
第二个版本将包含两个具有相同签名的方法(在类型删除之后),这在 Java 字节码中是不允许的。因此 JDK 编译器无法生成这样的类文件。我刚刚用十六进制编辑器编辑了一个类文件以创建一个具有此类方法的类,并且在启动程序时,我收到此错误:
Exception in thread "main" java.lang.ClassFormatError: Duplicate method name&signature in class file SameSignatureMethods
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClassCond(Unknown Source)
at java.lang.ClassLoader.defineClass(Unknown Source)
at java.security.SecureClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.access$000(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
Could not find the main class: SameSignatureMethods. Program will exit.
我开始的类(class)看起来像这样。我使用 String 和 Double 因为它们具有相同的名称长度:
public class SameSignatureMethods {
public <T extends String> String test() {
return null;
}
public <T extends Double> Double test() {
return null;
}
public static void main(String[] args) {
System.out.println(new SameSignatureMethods().<Double>test());
}
}
然后,使用十六进制编辑器,我将第一个方法的签名更改为 public <T extends String> Double test()
, 在类文件的两个地方,一个带有原始签名 ()Ljava/lang/Double;
,一个具有通用签名的 <T:Ljava/lang/String;>()Ljava/lang/Double;
.
关于java - 返回类型是删除的一部分吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4249499/