java - 返回类型是删除的一部分吗?

标签 java generics

有人可以解释为什么第二个类不能编译吗?

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/

相关文章:

java - 将一个字符串分成三个 block ?

java - flink可以使用固定数量的key到keyBy一个数据流均匀地避免数据倾斜吗?

java - HtppServlet 和 MongoClient

c# - 带有 ref 的扩展方法不适用于数组

C# 从泛型方法调用泛型方法

java - Apache Tomcat 不包含 conf/Catalina/localhost

java - 如何通过B类构造函数填充A类中的对象列表

c# - 泛型如何影响 C# 和 .NET 的设计?

java - 如何从泛型类型类创建对象

java - 如何从不带参数的java中的静态泛型函数进行转换?