我试图了解规范中是否存在 java 描述符和内部类签名之间存在差异的原因。(这里我是直接看class文件的内容,不过我用javap来说明)。
(注意,我在 JDK 1.6.0_33 和 1.7.0_05 上试过这个,当从 Java 7 中使用 javap 查看时,两者都有相同的问题- java 6 的 javap 似乎没有显示任何通用签名信息,根据 Sean 在下面的回答。)
更新:感谢那些讨论 - 我的看法是
- 描述符(不包含通用信息)是正确的。
- 签名(它是方法的一个属性,并且确实包含通用信息)不正确。<init> 方法的 SIGNATURE 的相关 ConstPool 条目是“ ConstantUTF8[(Ljava/util/list<TE;>)V] ”
- Java 6 中的 Javap 不看签名,只看描述符。(我猜!)
万一有人想知道,我没有使用 JAVAP,只是自己查看类文件,我只是使用 javap 来显示它。(因此不太可能是 javap 错误)。
考虑:
public class InnerClassTest1 {
public int getX() {
return new Inner1(new ArrayList<String>()).getX(4);
}
public class Inner1 {
private final List arg;
public Inner1(List arg) {
this.arg = arg;
}....
对比
public class InnerClassTest2 {
public int getX() {
return new Inner1(new ArrayList<String>()).getX(4);
}
public class Inner1<E> {
private final List<E> arg;
public Inner1(List<E> arg) {
this.arg = arg;
}.....
如果您查看内部类中 javap -cs 的输出,它们会出人意料地不同!
公共 org.benf.cfr.tests.InnerClassTest1$Inner1( org.benf.cfr.tests.InnerClassTest1, java.util.List); 签名:(Lorg/benf/cfr/tests/InnerClassTest1;Ljava/util/List;)V
对比
公共 org.benf.cfr.tests.InnerClassTest2$Inner1(java.util.List<E>); 签名:(Lorg/benf/cfr/tests/InnerClassTest2;Ljava/util/List;)V
...使用泛型的那个缺少外部类的隐式参数!(它正确存在于 InnerClassTest1 中)。
我在类文件文档中找不到任何东西来解释这一点——有人知道为什么会这样吗?
谢谢!
李。
更新 -
我已将示例文件放在http://www.benf.org/files/innerClassTest.tgz
鉴于肖恩在下面的回答,我尝试在 java 6 上使用 javap,我看到两者的输出相同,没有通用信息 - 这让我相信 java 6 的 javap 没有显示完整的签名信息?
我在 1.7.0_05-b06 上使用 javap 得到的确切输出是
public class org.benf.cfr.tests.InnerClassTest2$Inner1<E> {
final org.benf.cfr.tests.InnerClassTest2 this$0;
Signature: Lorg/benf/cfr/tests/InnerClassTest2;
public org.benf.cfr.tests.InnerClassTest2$Inner1(java.util.List<E>);
Signature: (Lorg/benf/cfr/tests/InnerClassTest2;Ljava/util/List;)V
Code:
0: aload_0
1: aload_1
2: putfield #1 // Field this$0:Lorg/benf/cfr/tests/InnerClassTest2;
5: aload_0
6: invokespecial #2 // Method java/lang/Object."<init>":()V
9: aload_0
10: aload_2
11: putfield #3 // Field arg:Ljava/util/List;
14: return
public int getX(int);
Signature: (I)I
Code:
0: iconst_2
1: ireturn
}