0
class World{

  <T extends Class1> World(TreeSet<? extends ClassA> set){
    *some code*
  }

  <T extends Class2> World(TreeSet<? extends ClassB> set){
    *some code*
  }

}

Above code shows error "name clash: < T#1>World and < T#2>World have the same erasure". Why the code does not compile? More importantly why compiler says they have same erasure? All questions on this site I have found related to this topic does not go into much depth to explain my problem.

NewStudent
  • 163
  • 8
  • 2
    Search for the error message.. no shortage of explanations. You are not the first to encounter it, and it has everything to do with "type erasure". Also, might be worthwhile to re-consider the assumptions in the title. – user2864740 Nov 01 '18 at 06:08
  • 2
    Possible duplicate of [Java generics type erasure: when and what happens?](https://stackoverflow.com/questions/339699/java-generics-type-erasure-when-and-what-happens) – dave Nov 01 '18 at 06:14
  • What do you think: How does the code look like after type erasure has been applied? And how many different signatures are there? – LuCio Nov 01 '18 at 07:30

1 Answers1

0

I examined the problem using Intellij Idea's Bytecode Viewer plugin on a class containing below method:

public <A extends Calendar> void fn(ArrayList<? extends File> abc){  //line number:11
  A a=(A)new Object();  //line 12
}  //line number:13

Below is the bytecode corresponding to this method from the bytecode viewer:

  // access flags 0x1
  // signature <A:Ljava/util/Calendar;>(Ljava/util/ArrayList<+Ljava/io/File;>;)V
  // declaration: void fn<A extends java.util.Calendar>(java.util.ArrayList<?extends java.io.File>)
public fn(Ljava/util/ArrayList;)V
  L0
    LINENUMBER 12 L0
    NEW java/lang/Object
    DUP
    INVOKESPECIAL java/lang/Object.<init> ()V
    CHECKCAST java/util/Calendar
    ASTORE 2
 L1
    LINENUMBER 13 L1
    RETURN
 L2
    LOCALVARIABLE this LMain; L0 L2 0
    LOCALVARIABLE abc Ljava/util/ArrayList; L0 L2 1
    // signature Ljava/util/ArrayList<+Ljava/io/File;>;
    // declaration: java.util.ArrayList<? extends java.io.File>
    LOCALVARIABLE a Ljava/util/Calendar; L1 L2 2
    // signature TA;
    // declaration: A
    MAXSTACK = 2
    MAXLOCALS = 3

Look at line 2 of above. The type parameters with proper bounds are kept although commented out. But the method signature does not contain any of the type parameters after compilation (line 4). We again see in line 10 the retained type parameter information is used for casting which corresponds to line 12 of original code. So conclusion is type parameters aren't outright replaced by their bounds. Your compiled file will retain information about both the type parameters and their bounds. This retained information will be used only when needed as determined by the compiler. And for some reason compiler does not think the method (or constructor) needs to have those information on their declaration in the compiled file (this explains "same erasure" error part). The reason has something to do with backward compatibility to Java versions when it did not have generic feature. So merely changing/adding/removing type parameters and/or their bounds does not overload method or constructor.


I know my answer is rough but not wrong to my knowledge. Please suggest anything I am missing in comment or post your own answer.

NewStudent
  • 163
  • 8