以下两个Java方法声明有何不同:
public <S extends Item> void withExtra1(S... extra) {
Collections.addAll(pool, extra);
}
和:
public void withExtra2(Item... extra) {
Collections.addAll(pool, extra);
}
它们不会,因为S
将被擦除为Item
,所以两个签名最终都以Item...
结尾。
Java规范说
Java编译器必须输出任何类,接口,构造函数或成员的通用签名信息,这些类,接口,构造函数或成员的Java编程语言中的通用签名将包括对类型变量或参数化类型的引用。
如果检查字节码,则可以看到具有泛型的方法具有不同的签名:
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
为#23 = Utf8 <S:LItem;>([TS;)V
] >>