5

好的,这是 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无法重命名成员。

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

4

3 回答 3

8

这称为模糊 (jls-6.4.2)。

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

于 2013-10-16T14:58:43.747 回答
1

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

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

非常糟糕的代码:)

于 2013-10-16T14:57:41.580 回答
1

我该如何解决这个问题?

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

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

    System.out.println(X.com);  // Works fine
}
于 2016-04-28T16:04:33.373 回答