【发布时间】:2018-01-09 19:38:39
【问题描述】:
以下用 Java-9 编写的正在运行的代码在 runtime 中给了我一个非常奇怪和有趣的异常:
Exception in thread "main" java.lang.NoSuchFieldError: super
at A$C.test(A.java:15)
at A.main(A.java:5)
代码:
public class A {
public static void main(String[] args) {
new C().test();
}
interface B {
private void test() {
}
}
static class C implements B {
void test() {
B.super.test();
}
}
}
我想知道:是这样设计的,还是理想情况下不应该编译这段代码,因此这是一个编译器错误? (我个人认为这是一个错误)。
UPD:提交了一个错误,ID : 9052188
UPD-2:看起来B.super.test() 通常是一个有效的构造,因为如果test() 方法是default,那么它可以正常工作。这个事实只会让事情变得更复杂。
【问题讨论】:
-
在这里猜测:A)这段代码是无效的(B超接口是一个接口,因此没有必要推迟到其中的方法的实现)和B)是的,编译器错误。所以合理的做法是:去写一个错误跟踪器问题;-)
-
当然是编译器的bug。编译时没有错误且事后未进行操作的程序永远不应在运行时获得
NoSuchFieldError(除非自己显式创建并抛出它),无论源代码是有效还是无效。 -
@GhostCat:不完全是。
B有一个private方法,它是可访问的,因为它是一个嵌套类并且我们在同一个顶级类中。但我想,B.super.test()不是正确的语法(但它是调用default方法的正确语法)。相比之下,((B)this).test()绝对是有效的语法,也可以正常工作。 -
@Andremoniy 好吧,是的,如果不深入,我们可以假设这可能是一个 JVM 错误,但是,我更深入了。
super访问永远不会使用名为super的字段来实现,此外,当通过((B)this).test()调用该方法时,它可以正常工作。剩下的唯一问题是B.super.test()是否有效并且应该像((B)this).test()那样编译,或者它是否无效并且应该被编译器拒绝。我倾向于后者。 -
我 already mentioned 认为
Interface.super.method()是调用default方法的正确方法,但据我在 JLS 中看到的,它 only 用于调用default方法。关于可访问性,JVM 绝不允许其他(普通)类访问private方法。这就是编译器为嵌套类生成这些合成access$n方法的原因。NoSuchFieldError并不表示 JVM 拒绝了方法访问。
标签: java javac java-9 nosuchfieldexception