当我尝试编译以下代码时,我得到编译错误:
unexpected type System.out.println( new Test().C.i );
^
required: class,package
found: value
Run Code Online (Sandbox Code Playgroud)
class Test {
class C {
static final int i = 0;
}
public static void main(String... z) {
System.out.println( new Test().C.i );
}
}
Run Code Online (Sandbox Code Playgroud)
但是,如果我改变 new Test().C.i到new Test().new C().i它编译就好了.
为什么?如果我在C中是静态的,那么我不应该实例化C.我应该只能通过类C而不是C对象来调用它.
我错过了什么?
问题是"." Identifier在Java语法中,期望标识符引用变量而不是类型.
这是在6.5.6.2. Qualified Expression NamesJLS(以及其他地方)中指定的:
如果Q是一个命名类类型的类型名称(§8(Classes)),那么:
如果类类型中没有一个可访问的(§6.6)成员是名为Id的字段,则会发生编译时错误.
否则,如果单个可访问成员字段不是类变量(即,它未声明为静态),则会发生编译时错误.
否则,如果类变量声明为final,则Q.Id表示类变量的值.
表达式Q.Id的类型是捕获转换后的类变量的声明类型(第5.1.10节).
如果Q.Id出现在需要变量而不是值的上下文中,则会发生编译时错误.
否则,Q.Id表示类变量.
表达式Q.Id的类型是捕获转换后的类变量的声明类型(第5.1.10节).
请注意,此子句涵盖枚举常量(第8.9节)的使用,因为它们始终具有相应的最终类变量.
虽然我完全可以理解为什么你会认为它的工作原理 - 我实际上期望它能够正常工作 - 但这并不是什么大问题:因为总有一部分i你可以参考它Test.C.i.如果i是非静态的new Test().new C().i将是访问它的正确方法.
另一种看待它的方法是阅读15.8.主表达式具有主表达式的实际语法(这是我们在这里处理的):它允许ClassInstanceCreationExpression(这就是为什么new Test().new C().i有效)以及FieldAccess(Test.C.i因为"类"以递归方式解析 - 只有最后一个标识符必须然后参考一个字段).
Jar*_*ler -2
我认为之所以new Test().new C().i有效,是因为 Test 类是顶级类,并且被视为static. 如果您要将内部类更改C为静态,那么就new C().i可以了。
但是,您不应该以非静态方式访问静态成员。
要访问静态字段,请执行以下操作:
System.out.println(C.i);
Run Code Online (Sandbox Code Playgroud)
编辑:
对于那些说类Test不是静态的人,请参阅此 stackoverflow答案。
根据定义,所有顶级类都是静态的。
静态归结为类的实例可以独立存在。或者,相反:如果没有外部类的实例,非静态内部类(=实例内部类)就不能存在。由于顶级类没有外部类,因此它只能是静态的。
因为所有顶级类都是静态的,所以在顶级类定义中使用 static 关键字是没有意义的。
只是为了向您展示以这种方式访问静态字段的想法是多么愚蠢,我创建了以下项目:
class Test {
class C {
static final int i = 0;
}
public static void main(String[] args) {
// BAD:
System.out.println(new Test().new C().i);
// Correct:
System.out.println(C.i);
}
}
Run Code Online (Sandbox Code Playgroud)
如果您编译该类并在jd-gui中查看它,您可以看到它是如何编译的:
class Test {
public static void main(String[] args) {
void tmp13_10 = new Test(); tmp13_10.getClass(); new C(); System.out.println(0);
System.out.println(0);
}
class C {
static final int i = 0;
C() {
}
}
}
Run Code Online (Sandbox Code Playgroud)