gavenkoa :
How do following 2 Java method declarations differ:
public <S extends Item> void withExtra1(S... extra) {
Collections.addAll(pool, extra);
}
and:
public void withExtra2(Item... extra) {
Collections.addAll(pool, extra);
}
andresp :
The Java spec says
A Java compiler must output generic signature information for any class, interface, constructor or member whose generic signature in the Java programming language would include references to type variables or parameterized types.
If you check the bytecode you can see the method with generics has a different signature:
public <S extends Item> void withExtra1(S...);
descriptor: ([LItem;)V
flags: (0x0081) ACC_PUBLIC, ACC_VARARGS
Code:
stack=2, locals=2, args_size=2
0: aload_0
1: getfield #2 // Field pool:Ljava/util/List;
4: aload_1
5: invokestatic #3 // Method java/util/Collections.addAll:(Ljava/util/Collection;[Ljava/lang/Object;)Z
8: pop
9: return
LineNumberTable:
line 9: 0
line 10: 9
LocalVariableTable:
Start Length Slot Name Signature
0 10 0 this LItem;
0 10 1 extra [LItem;
LocalVariableTypeTable:
Start Length Slot Name Signature
0 10 1 extra [TS;
Signature: #23 // <S:LItem;>([TS;)V
public void withExtra2(Item...);
descriptor: ([LItem;)V
flags: (0x0081) ACC_PUBLIC, ACC_VARARGS
Code:
stack=2, locals=2, args_size=2
0: aload_0
1: getfield #2 // Field pool:Ljava/util/List;
4: aload_1
5: invokestatic #3 // Method java/util/Collections.addAll:(Ljava/util/Collection;[Ljava/lang/Object;)Z
8: pop
9: return
LineNumberTable:
line 13: 0
line 14: 9
LocalVariableTable:
Start Length Slot Name Signature
0 10 0 this LItem;
0 10 1 extra [LItem;
#23
in the constant pool is #23 = Utf8 <S:LItem;>([TS;)V
You can access this information at runtime using reflection:
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class Item {
List<Item> pool;
public static void main(String[] args) {
for (var m : Item.class.getMethods())
System.out.println(m.getName() + " " +
Arrays.toString(m.getGenericParameterTypes()));
}
public <S extends Item> void withExtra1(S... extra) {
Collections.addAll(pool, extra);
}
public void withExtra2(Item... extra) {
Collections.addAll(pool, extra);
}
}
stdout:
main [class [Ljava.lang.String;]
withExtra1 [S[]]
withExtra2 [class [LItem;]
wait [long]
wait [long, int]
wait []
equals [class java.lang.Object]
toString []
hashCode []
getClass []
notify []
notifyAll []