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

好的,这里是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完全阻止从X访问com.*包。 但是,这并未得到彻底应用。 以下工作,例如:

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

我的问题:

  • 这种行为如何从JLS中certificate是正确的?
  • 我该如何解决这个问题

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

更新 :我认为它实际上可能是类似这样的问题: 为什么我不能在Java中“静态导入”一个“等于”方法?

这称为模糊(jls-6.4.2)。

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

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

更重要的是,每次你将实现一个X,它将导致一个新的X:我可以在这里预测一次内存爆炸。

非常糟糕的代码:)

我该如何解决这个问题?

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

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