【问题标题】:How to fully qualify a class whose package name collides with a local member name?如何完全限定包名与本地成员名冲突的类?
【发布时间】:2013-10-24 18:14:00
【问题描述】:

好的,这是 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 如何证明这种行为是合理的?
  • 如何解决此问题

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

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

【问题讨论】:

  • 生成的代码,嗯?我知道 JAXB 使用绑定文件来更改包名称以避免在从模式和 WSDL 生成代码时出现类似问题。不确定这是否适合您。
  • @FrustratedWithFormsDesigner:是的,重命名包是一种选择。但由于我是代码生成器的作者(jOOQ,而不是 JAXB),我想知道更多:-)

标签: java visibility java-7 jls


【解决方案1】:

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

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

非常糟糕的代码:)

【讨论】:

  • 你是对的。我添加了 static 关键字,因为这与问题无关。我只是(错误地)删除了它以使示例更简单:-) 我仍然遇到同样的错误。
【解决方案2】:

This is called obscuring (jls-6.4.2).

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

【讨论】:

  • 啊,是的,我之前在静态导入一些equals 方法时遇到过这种情况:stackoverflow.com/q/7890853/521799。你不知道解决方法吗? :-)
  • @LukasEder 更改冲突名称 :) 使用您的 JAXB 或其他代码生成器,可能可以配置命名策略。
  • 是的,但是我会让用户解决这个问题。我想通过一些巧妙的解决方法在代码生成器中实现一个解决方案
  • @LukasEder 如果您控制代码生成器,那么命名策略可能是您最好的选择,比较字段/变量/类型/包名称。
  • @LukasEder 粗体句是关键,可悲的是:(。
【解决方案3】:

我该如何解决这个问题?

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

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

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

【讨论】:

  • 感谢您为完整起见回答这个问题;)在我当时的情况下,这当然不是一个选择,因为在这种特定情况下导入语句不可用......
  • 不客气。这个问题是从一个相关的问题链接的,它似乎是一个被忽视的问题解决方案。遗憾的是,这不是您特定情况的选择。 (这是一个制作我的死灵法师/复兴徽章的机会。)
  • 确实,这些徽章在某些时候肯定会派上用场:)
猜你喜欢
  • 2015-02-26
  • 1970-01-01
  • 2019-11-23
  • 1970-01-01
  • 2020-11-12
  • 1970-01-01
  • 2014-06-07
  • 2014-04-30
  • 1970-01-01
相关资源
最近更新 更多