dur*_*597 12 java stack-overflow generics types compilation
我正在阅读这篇关于"Java中的奇怪事物"的文章,我遇到了一个有趣的概念:不可判定的类型.
考虑以下三个类/接口:
public interface Type<T> { }
Run Code Online (Sandbox Code Playgroud)
public class D<P> implements Type<Type<? super D<D<P>>>> { }
Run Code Online (Sandbox Code Playgroud)
public class WildcardTest {
Type<? super D<Byte>> d = new D<Byte>();
}
Run Code Online (Sandbox Code Playgroud)
显然问题是它是否D是不可判定的Type<? super D<Byte>>; 谁能进一步解释这个?
javac 1.8.0_60StackOverflowError尝试编译时抛出很长时间WildcardTest:
The system is out of resources.
Consult the following stack trace for details.
java.lang.StackOverflowError
at com.sun.tools.javac.code.Types$UnaryVisitor.visit(Types.java:4640)
at com.sun.tools.javac.code.Types$26.visitClassType(Types.java:3834)
at com.sun.tools.javac.code.Types$26.visitClassType(Types.java:3826)
at com.sun.tools.javac.code.Type$ClassType.accept(Type.java:778)
at com.sun.tools.javac.code.Types$UnaryVisitor.visit(Types.java:4640)
at com.sun.tools.javac.code.Types$26.visitClassType(Types.java:3839)
at com.sun.tools.javac.code.Types$26.visitClassType(Types.java:3826)
at com.sun.tools.javac.code.Type$ClassType.accept(Type.java:778)
at com.sun.tools.javac.code.Types$UnaryVisitor.visit(Types.java:4640)
at com.sun.tools.javac.code.Types$26.visitClassType(Types.java:3839)
at com.sun.tools.javac.code.Types$26.visitClassType(Types.java:3826)
at com.sun.tools.javac.code.Type$ClassType.accept(Type.java:778)
at com.sun.tools.javac.code.Types$UnaryVisitor.visit(Types.java:4640)
at com.sun.tools.javac.code.Types$26.visitClassType(Types.java:3839)
at com.sun.tools.javac.code.Types$26.visitClassType(Types.java:3826)
at com.sun.tools.javac.code.Type$ClassType.accept(Type.java:778)
Run Code Online (Sandbox Code Playgroud)
此代码也会崩溃整个Eclipse IDE.
正如 Tunaki 在评论中指出的那样,这可以追溯到Pierce( TAPL作者)共同撰写的一篇微软研究论文。事实上,问题是泰特等人。给出的是附录 A 中的示例 2(带有、和)。Byte = TType = ND = C
堆栈溢出
\n首先,让我们弄清楚为什么它会破坏堆栈。为此,最好提醒自己编译器检查类型的方式与我们几乎相同。我们遇到的问题它也会遇到。
\n// To be determined:\nD<Byte> <: Type<? super D<Byte>>\n\n// using D<P> implements Type<Type<? super D<D<P>>>>\n\nType<Type<? super D<D<Byte>>>> <: Type<? super D<Byte>>\n\n// The outermost type constructor (Type) matches. For the\n// suptyping relationship to hold, we have to test the type\n// arguments. (Sides are flipped due to contravariance.)\n\nD<Byte> <: Type<? super D<D<Byte>>>\n\n// Mhh\xe2\x80\xa6 That looks an awful lot like above.\n// Feel free to rinse and repeat until your "stack" blows too\xe2\x80\xa6 ;)\nRun Code Online (Sandbox Code Playgroud)\n皮尔斯等人。描述了与论文第 3 节中的示例 2 类似的回归。它略有不同,因为 Java 不允许类型变量的下限,只允许通配符的下限。
\n可以做什么?
\n与 Pierce 等人给出的示例 1 类似,此回归遵循一种模式。这种模式可以被编译器检测到,并且可以假设子类型关系在共归纳解释下成立。(这与 F 有界多态性的推理相同,即Enum<E extends Enum<E>>。您输入类似的无限回归而不矛盾。)
无法确定?
\n给定的问题可以通过更智能的算法来解决。Java 的类型系统是否可判定仍然是一个悬而未决的问题。
\n如果 Java 允许类型参数的下限,那么它将是不可判定的(半可判定的)。然而,皮尔斯等人在他们的论文中。定义可以使此类类型系统再次可判定的限制。顺便说一句,这些限制被 Scala 采用了,讽刺的是,Scala 拥有图灵完备的类型系统。
\n