为什么通用签名中指定了非静态内部类的类型变量?

时间:2015-05-21 11:14:07

标签: java generics

当我定义一个类型时:

class Bar<S> {
  /* non-static */ class Foo<U extends Foo<U>> { }
}

Java编译器为创建的类型生成以下通用签名:

<U:Lfoo/Bar<TS;>.Foo<TU;>;>Ljava/lang/Object;

如果内部类型被定义为静态,则通用签名定义为:

<U:Lfoo/Bar$Foo<TU;>;>Ljava/lang/Object;

不同之处在于Foo的外部类Bar的类型变量也存储在签名中。我现在想知道为什么Java编译器会以这种方式在签名中添加此信息。我无法理解为什么它会对U进行适当的定义有所不同,因为U绝不依赖于S或外部类。 Java编译器试图解决什么样的困境?

我想知道这个信息何时实际用于解析类型的示例。此外,我注意到Java反射API不会为静态或非静态情况返回不同的结果。

1 个答案:

答案 0 :(得分:2)

你的假设是错误的。您在(JVM)类型签名中看到的是U的上限。该上限为Foo<U>,或者在完全限定时为foo.Bar<S>.Foo<U>。尝试在Foo<U>范围之外表示Bar。 javac会对你大喊大叫。 ;)

class Bar<S> {
  /* non-static */ class Foo<U extends Foo<U>> {}
}

Bar.Foo<?> foo = null; // error
Bar<String>.Foo<?> foo = null; // fine

编辑:您看到的TS;不是类型参数,而是类型参数。完全限定边界并使用另一个参数使其显而易见:

class Baz {}

class Bar<S> {
  /* non-static */ class Foo<U extends Bar<Baz>.Foo<U>> {}
}