9

静态内部类M和静态成员M[of class C] 如何共享相同的名称?

以下代码生成“White”作为输出:

public class Amazed{

    public static void main(String[] args) {
        System.out.println(B.M.W);
    }
}

class B {
    public static class M {       
        static String W = "Black";
    }

    static C M = new C();
}

class C {
    String W = "White";
}

如何访问成员对象而不是静态类成员:W [“Black”]

如果我想访问静态类 M 中的成员,该怎么做?

4

4 回答 4

2

Java 语言规范的第 6 章(尤其是第 6.5 节)详细说明了 Java 如何整理出特定标识符在特定上下文中的含义的可怕细节。规则相当复杂,但粗略地说,Java 有六个命名空间:

  • 包名称
  • 类型名称
  • 字段(变量)名称
  • 方法名称
  • 局部变量名(包括参数)
  • 标签

每个名称空间中的实体都可以使用相同的标识符。请注意,类型(类)名称和字段名称是分开存在的,这解释了为什么您的代码是合法的。

同一名称空间中的继承名称有时也可以被遮蔽或屏蔽。有时标识符是模棱两可的;然后需要以某种方式对其进行限定(例如,使用包名),否则编译器会抱怨。

代码混淆器利用这一点非常有利,以至于您最终可以得到一个名为的包a.a和一个名为ain的类a(也将被标识为a.a)。更不用说 Java 关键字喜欢dofor是 .class 文件中的合法名称(但不是 Java 源代码)。它有助于使逆向工程成为真正的熊。

于 2013-07-26T17:32:11.890 回答
1

该变量掩盖了同名的类型。如果名称可以解释为变量或类型,则首选变量。

您可以通过不给它们相同的名称来避免这种情况。

来自 Java 语言规范,第 6.4.2 节:模糊

6.4.2. 遮蔽

简单名称可能出现在可能被解释为变量、类型或包的名称的上下文中。在这些情况下,§6.5 的规则指定将优先选择变量而不是类型,并且将优先选择类型而不是包。因此,有时可能无法通过其简单名称来引用可见类型或包声明。我们说这样的声明是模糊的。

于 2013-07-26T17:29:21.800 回答
0

在大家的帮助和小游戏之后,我发现即使没有为内部类创建对象,我们也可以访问成员 W“Black”。

只需使用此语句

M.W

但我无法弄清楚访问级别。[因为它是公开的?] 即使没有公开它也有效。怎么样?

于 2013-07-26T17:42:43.560 回答
0

在您可以实例化的特定情况下,M您可以使用可以以非静态方式访问静态的事实:

public class Amazed{
   @SuppressWarnings("static-access")
   public static void main(String[] args) {
       B.M val = new B.M();
       System.out.println(val.W);
   }
}

class B {
   public static class M {       
       static String W = "Black";
   }

   static C M = new C();
}

class C {
   String W = "White";
}

上面将打印“黑色”,因为您通过B.M. 当然,这在生产代码中绝不是一个好主意,因为不应以非静态方式访问静态字段。同样,它要求您创建一个B.M.

于 2013-07-26T17:27:11.993 回答