Is the return type part of the erase?

Can someone explain why the second class does not compile?

1 Compiled using javac and JDK 6 (Eclipse will complain about this code)

public class SameSignatureMethods { public <T extends String> Boolean test() { return true; } public <T extends Character> Double test() { return 1d; } } 

2 A small change in this example, and compilation failed:

 name clash: <T>test() and <T>test() have the same erasure 

The only change is the return type of the method:

 public class SameSignatureMethods { public <T extends String> Boolean test() { return true; } public <T extends Character> Boolean test() { return true; } } 

Here's what the main method for the first class will look like:

 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()); } 
+7
java generics
source share
3 answers

So, the JDK compiler compiles the first version, but not the second, and the Eclipse compiler does not compile either of the two versions.

In terms of Java bytecode, the first version contains two different methods (after type erasure), namely public java.lang.Boolean test() and public java.lang.Double test() , which is absolutely true. The JDK compiler and the Eclipse compiler sometimes generate such methods when you override common methods, but then they are marked as synthetic bridge methods.

The second version will contain two methods with the same signature (after erasing the type), which is not allowed in Java bytecode. Therefore, the JDK compiler cannot create such a class file. I just edited a class file with a hex editor to create a class with such methods, and after starting the program I get this error:

 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. 

The class I started with is as follows. I used String and Double because they have the same name length:

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

Then, using a hex editor, I replaced the signature of the first method with public <T extends String> Double test() in two places in the class file, one with the raw signature ()Ljava/lang/Double; , one with a common signature <T:Ljava/lang/String;>()Ljava/lang/Double; .

+4
source share

It looks like you managed to terribly confuse your compiler:

  • The return type is not part of the signature. The compiler cannot use the return type to indicate which method is being called.

  • In your example, the common stuff clogged in the method signature does not affect the return type.

  • Also saying <T extends String> does not make sense, you cannot extend the final type. (Hmm, this is just a warning, this does not stop compiling)

You are wondering why the second class does not compile, I wonder why the first class compiles. As in the first class, compilation, albeit with a warning. Removing a pointed bracket results in a "Duplicate Method" error, which should appear independently. There must be a compiler error.

+2
source share

In the first class ( SameSignatureMethods ), 2 methods at runtime return Boolean and Double respectively. In the second class, methods return a Boolean .

<T extends String> before defining a method does not mean that it is a return type.

Perhaps you want to do something like this:

 public <T extends String> T test() { return obj;// obj could be a String } 

However, common types are erased at run time, and the method above becomes

 public Object test() { return obj;// obj could be a String } 
+1
source share

All Articles