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

Posted

技术标签:

【中文标题】如何完全限定包名与本地成员名冲突的类?【英文标题】: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),我想知道更多:-) 【参考方案1】:

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

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

非常糟糕的代码:)

【讨论】:

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

This is called obscuring (jls-6.4.2).

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

【讨论】:

啊,是的,我之前在静态导入一些equals 方法时遇到过这种情况:***.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

【讨论】:

感谢您为完整起见回答这个问题;)在我当时的情况下,这当然不是一个选择,因为在这种特定情况下导入语句不可用...... 不客气。这个问题是从一个相关的问题链接的,它似乎是一个被忽视的问题解决方案。遗憾的是,这不是您特定情况的选择。 (这是一个制作我的死灵法师/复兴徽章的机会。) 确实,这些徽章在某些时候肯定会派上用场:)

以上是关于如何完全限定包名与本地成员名冲突的类?的主要内容,如果未能解决你的问题,请参考以下文章

MyBatis学习总结——解决字段名与实体类属性名不相同的冲突(转载)

Mybatis解决字段名与实体类属性名不相同的冲突

MyBatis——解决字段名与实体类属性名不相同的冲突

MyBatis学习总结——解决字段名与实体类属性名不相同的冲突

MyBatis学习总结——解决字段名与实体类属性名不相同的冲突

MyBatis学习总结——解决字段名与实体类属性名不相同的冲突