As far as I can tell, C++ compiler instantiate (implicitly or explicitly) template function for a given template argument and at runtime we have different function for each that template argument.
In Java there is no concept such like generic instantination or specialization. For example,
public class MyClass{
public void <T> method(T t){ }
}
We cannot instantiate and specialize it something like in C++
public void <Integer> MyClass::method(Integer t){ //not valid in Java
//...
}
Instead type erasure came, so at runtime we have a single ungenerified version of the generic-method which is possible to override.
Take a look at this simple class:
public class Main{
public static void main(String[] args){
Main m = new Main();
m.method(10);
m.methodNumber(10);
m.methodNumberAnd(10);
m.methodNumberAnd2(10);
m.methodInteger(10);
}
public <T> void method(T t){ }
public <T extends Number> void methodNumber(T t){ }
public <T extends Number & java.io.Serializable> void methodNumberAnd(T t){ }
public <T extends java.io.Serializable & java.lang.Comparable<T>> void methodNumberAnd2(T t){ }
public void methodInteger(Integer t){ }
}
And the run
javac Main.java
javap -c Main.class
It gives this:
public class Main {
public Main();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: new #2 // class Main
3: dup
4: invokespecial #3 // Method "<init>":()V
7: astore_1
8: aload_1
9: bipush 10
11: invokestatic #4 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
14: invokevirtual #5 // Method method:(Ljava/lang/Object;)V
17: aload_1
18: bipush 10
20: invokestatic #4 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
23: invokevirtual #6 // Method methodNumber:(Ljava/lang/Number;)V
26: aload_1
27: bipush 10
29: invokestatic #4 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
32: invokevirtual #7 // Method methodNumberAnd:(Ljava/lang/Number;)V
35: aload_1
36: bipush 10
38: invokestatic #4 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
41: invokevirtual #8 // Method methodNumberAnd2:(Ljava/io/Serializable;)V
44: aload_1
45: bipush 10
47: invokestatic #4 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
50: invokevirtual #9 // Method methodInteger:(Ljava/lang/Integer;)V
53: return
public <T> void method(T);
Code:
0: return
public <T extends java.lang.Number> void methodNumber(T);
Code:
0: return
public <T extends java.lang.Number & java.io.Serializable> void methodNumberAnd(T);
Code:
0: return
public <T extends java.io.Serializable & java.lang.Comparable<T>> void methodNumberAnd2(T);
Code:
0: return
public void methodInteger(java.lang.Integer);
Code:
0: return
}
Notice the signatures of the compiled methods:
Method method:(Ljava/lang/Object;)V
Method methodNumber:(Ljava/lang/Number;)V
Method methodNumberAnd:(Ljava/lang/Number;)V
Method methodNumberAnd2:(Ljava/io/Serializable;)V
Method methodInteger:(Ljava/lang/Integer;)V
As @Eugene noted generic types will erase to the first type bound in case of &
.