繁体   English   中英

在Java中访问内部类中的静态最终字段

[英]Accessing Static Final Fields in Inner Classes in Java

当我尝试编译以下代码时,出现编译错误:

unexpected type System.out.println( new Test().C.i );
                                    ^
required: class,package 
found: value

class Test {

    class C {
        static final int i = 0;    
    }

    public static void main(String... z) {
        System.out.println( new Test().C.i  );
    }

}

但是,如果我将new Test().Ci更改为new Test().new C().i则可以正常编译。

为什么? 如果我在C中是静态的,则不必实例化C。我应该只能通过类C而不是C对象来调用它。

我想念什么?

问题是"." Identifier "." Identifier在Java语法期望标识符以引用变量,而不是一个类型。

这在6.5.6.2. Qualified Expression Names指定6.5.6.2. Qualified Expression Names JLS的6.5.6.2. Qualified Expression Names (以及其他地方):

如果Q是用于命名类类型的类型名(第8节(类)),则:

如果类类型的字段中没有一个唯一可访问的成员(第6.6节),该成员名为Id,则会发生编译时错误。

否则,如果单个可访问成员字段不是类变量(也就是说,它不是声明为静态的),则会发生编译时错误。

否则,如果将类变量声明为final,则Q.Id表示类变量的值。

表达式Q.Id的类型是捕获转换(第5.1.10节)之后类变量的声明类型。

如果Q.Id出现在需要变量而不是值的上下文中,则会发生编译时错误。

否则,Q.Id表示类变量。

表达式Q.Id的类型是捕获转换(第5.1.10节)之后类变量的声明类型。

请注意,此子句涵盖枚举常量的使用(第8.9节),因为它们始终具有相应的最终类变量。

尽管我绝对可以理解为什么您会认为它可以那样工作的逻辑-我实际上希望它也能工作-但这没什么大不了的:由于始终只有i一个人可以参考它Test.Ci 如果i是非静态的,那么new Test().new C().i将是访问它的正确方法。

另一种看待它的方法是阅读15.8。 基本表达式具有基本表达式的实际语法(这是我们在此处处理的):它允许ClassInstanceCreationExpression (这就是new Test().new C().i起作用的原因)以及FieldAccess (对于Test.Ci起作用)的FieldAccess Test.Ci因为“类”是递归解析的-那么只有最后一个标识符必须引用一个字段。

我认为new Test().new C().i起作用的原因是因为Test类是顶级类,被视为static 如果要将内部类C更改为静态,那么new C().i将起作用。

但是,你应该在非静态的方式访问静态成员。

要访问您的静态字段,请执行以下操作:

System.out.println(C.i);

编辑:

对于那些说类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);
    }

}

如果编译该类并在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() {
    }
  }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM