如何完全限定包名与本地成员名冲突的类?

时间:2013-10-16 14:52:12

标签: java visibility java-7 jls

好的,这里是JLS专家的一个非常好奇的Java 7语言难题。以下代码不能用javac和Eclipse编译:

package com.example;

public class X {
    public static X com = new X();

    public void x() {
        System.out.println(com.example.X.com);
        // cannot find symbol  ^^^^^^^
    }
}

好像成员com完全阻止了com.*X个包的访问权限。然而,这并未得到彻底应用。以下工作,例如:

public void x() {
    System.out.println(com.example.X.class);
}

我的问题:

  • 这种行为如何从JLS中得到证明?
  • 如何解决此问题

请注意,这只是对生成代码中的实际问题的简化,其中需要com.example.X的完全限定,并且无法重命名com成员。

更新:我认为它实际上可能是类似这样的问题:Why can't I "static import" an "equals" method in Java?

3 个答案:

答案 0 :(得分:6)

This is called obscuring (jls-6.4.2).

  

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

答案 1 :(得分:1)

您的属性com.example.X.com不是静态的,因此无法通过X类以静态方式访问它。您只能通过X的实例访问它。

不仅如此,每次你实现一个X,它都会导致一个新的X:我可以在这里预测内存爆炸。

非常糟糕的代码:)

答案 2 :(得分:1)

  

如何解决此问题?

在这里使用完全限定的类名可能是个问题,因为通常,包名和变量名都以小写字母开头,因此可能会发生冲突。但是,您不需要使用完全限定的类名来获取类的静态成员的引用;你可以通过类名来引用它。由于类名应以大写字符开头,因此它们不应与包名或变量发生冲突。 (并且您可以使用其完全限定的类名导入任意类而不会出现问题,因为import语句永远不会混淆包名称的变量名。)

public void x() {
    // System.out.println(com.example.X.com);
    // cannot find symbol     ^^^^^^^

    System.out.println(X.com);  // Works fine
}