以下两个案例似乎有效:
public class A {
private class B {
public static final String str = "str";
}
}
public class A {
private static class B {
public static final String str = new String("str");
}
}
但是以下给出了注释中指定的错误:
public class A {
private class B {
//The field str cannot be declared static;
//static fields can only be declared in static or top level types
public static final String str = new String("str");
}
}
为什么在前两种情况下允许它以及为什么它在最后一种情况下引起问题?
答案 0 :(得分:4)
这是JLS, section 8.1.3所要求的。我从来没有看到它的原因,但我怀疑一个非静态的内部类需要一个外部类的实例,但声明为静态破坏了这个概念,并允许它们创建一整套其他规则来处理就是那个被认为不值得的案子。而当它是静态的时,它就像任何其他类一样,恰好恰好位于同一个源文件中。
答案 1 :(得分:1)
我猜这个限制是由于new String("str")
的实施方式。使用文字字符串初始化成员可以使用常量池中的条目来完成,但new String("str")
需要实际执行代码,因此必须使用静态init方法中的实际字节码来完成。
棘手的内部阶级方案让我头疼只是考虑它(它内部真的是一个kludge),所以我无法准确解释问题是什么,但我怀疑静态init方法在不适当的时候运行如上所述,因此结果不可靠或系统无法处理静态init方法中的错误导致的异常。
答案 2 :(得分:0)
JLS明确说明了这一限制;见Yishai的答案。
“为什么”的一个可能的解释是,期望非常量静态初始化表达式可以引用封闭类中的静态或非静态。第一种可能导致类(静态)初始化的排序中的概念或实现困难。第二个是无法实现的,并且会导致难以理解的编译错误。 (考虑一下新手在简单方法中对静态/非静态访问限制进行操作的频率。)
我认为他们只是采取了简单的方法并禁止了这一点。 (KISS为我工作......)他们可能认为他们可以在以后的版本中放宽限制,但后来没有看到有必要这样做。