【问题标题】:Name clash in java importsjava导入中的名称冲突
【发布时间】:2013-02-06 21:10:00
【问题描述】:

除非我们 change the compiler,否则 Java 会错过 import X as Y 语法,这在像我这样的情况下会很有用:此时,我正在处理一个项目,该项目有多个具有相同名称但属于不同包的类.

我想要类似的东西

import com.very.long.prefix.bar.Foo as BarFoo
import org.other.very.long.prefix.baz.Foo as BazFoo

class X {
    BarFoo a;
    BazFoo b;
    ...
}

相反,我完成了类似的事情

class X {
    com.very.long.prefix.bar.Foo a;
    org.other.very.long.prefix.baz.Foo b;
    ...
}

这似乎很有害,但在我的具体情况下,我需要使用水平滚动来浏览我的源代码,这会使得已经一团糟的程序变得更糟。

根据您的经验,这种情况下的最佳做法是什么?

【问题讨论】:

    标签: java import


    【解决方案1】:

    我感受到你的痛苦,无论你使用哪种解决方案,有两个同名的类这一事实已经足够令人困惑了。

    有几个解决方案解决方法:

    1. 如果这是您的代码,只需重命名其中一个(或两个)
    2. 如果这是库(更有可能)导入更常用的类,请按照 Jeff Olson 的建议完全限定另一个类。
    3. 如果可能的话,首先尽量避免让他们在同一个班级。
    4. 您可以编写自己的BarFooBazFoo,它们除了扩展它们各自的Foo 类之外什么也不做,从而为它们提供自己的名称。您甚至可以将它们定义为内部类。示例:
    private BarFoo extends com.very.long.prefix.bar.Foo{
    //nothing, except possibly constructor wrappers
    }
    
    private BazFoo extends com.very.long.prefix.bar.Foo{
    //nothing, except possibly constructor wrappers
    }
    
    class X {
       BarFoo a;
       BazFoo b;
       //...
    }
    

    不过也有一些缺点:

    • 你必须重新定义构造函数
    • 如果您需要将它传递给明确检查其getClass 的函数,它不会是完全相同的类。

    您可以通过包装 Foo 类而不是扩展它们来解决这些缺点,例如:

    private BarFoo {
       public com.very.long.prefix.bar.Foo realFoo;
    }
    
    private BazFoo extends com.very.long.prefix.bar.Foo{
      public com.very.long.prefix.baz.Foo realFoo;
    }
    
    class X {
        BarFoo a;
        BazFoo b;
    
        //now if you need to pass them
        someMethodThatTakesBazFoo(b.realFoo);
    }
    

    选择最简单的解决方案,祝你好运!

    【讨论】:

      【解决方案2】:

      最佳实践是重构代码。

      任何一个类都不应该有相同的名称,因为在同一个类中使用它们是很正常的,因此为它们选择相同的名称不是一个明智的选择。所以至少应该重命名其中之一。

      或者在同一个类中使用它们是不正常的,因为它们属于完全不同的抽象级别(例如数据库访问代码和 UI 代码),并且应该重构代码以使用每个必须使用的类而不是其他地方。

      【讨论】:

        【解决方案3】:

        在这些情况下,我通常所做的就是在我的班级中导入最常用的 Foo,然后完全限定另一个:

        import com.very.long.prefix.bar.Foo
        
        class X {
            Foo a;
            org.other.very.long.prefix.baz.Foo b;
            ...
        }
        

        【讨论】:

          【解决方案4】:

          在这里。

          随着时间的推移,我实际上制定了一种策略来解决 Java 语言的这一限制。我不知道这是否有一些缺点(到目前为止我从未发现任何缺点),但如果有,请在这个问题中发表评论。

          这个想法是用而不是包替换完全限定名称的最后一部分,并将实际的类定义为静态内部类。

          class Bar {
              static class Foo { ... }
          }
          

          这样我们就有了类似的东西

          import f.q.n.Bar
          import other.f.q.n.Baz
          
          ...
          Bar.Foo a;
          Bar.Foo b;
          

          这实际上是一种非常干净的方式。当然它只适用于你控制的类,而不适用于库。

          已知的缺点

          【讨论】:

            【解决方案5】:

            您可能想看看Kotlin,它与Java 兼容。

            如果 Kotlin 中存在名称冲突,您可以使用 as 关键字在本地重命名冲突实体来消除歧义:

            import foo.Bar // Bar is accessible
            import bar.Bar as bBar // bBar stands for 'bar.Bar'
            

            您可以在https://kotlinlang.org/docs/reference/packages.html找到更多信息

            【讨论】:

              猜你喜欢
              • 2021-06-06
              • 2018-11-27
              • 1970-01-01
              • 2019-05-18
              • 2018-12-18
              • 2019-10-20
              • 2011-11-24
              • 1970-01-01
              • 2011-08-31
              相关资源
              最近更新 更多