静态内部类和类的静态成员共享SAME NAME?

时间:2013-07-26 17:08:06

标签: java static-methods static-members

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

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

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 个答案:

答案 0 :(得分:2)

Chapter 6 of the Java Language Specification(特别是Section 6.5)详细说明了Java如何排序特定标识符在特定上下文中的含义。规则相当复杂,但粗略地说,Java有六个名称空间:

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

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

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

代码混淆器使用它非常有利,最终可以在程序包a.a中找到名为a的程序包和一个名为a的类(也可以识别它)作为a.a)。更不用说像dofor这样的Java关键词在.class文件中是合法的名称(但在Java源代码中却不是)。它有助于使逆向工程变成真正的熊。

答案 1 :(得分:1)

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

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

来自Java语言规范,section 6.4.2: Obscuring

  

6.4.2。模糊

     

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

答案 2 :(得分: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的实例。

答案 3 :(得分:0)

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

只需使用此声明

M.W

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