不同包中相同的类名

33

同一个类可以存在于多个包中吗?换句话说,我可以在com.test.package1com.test.package2中都有一个名为Foo.java的类吗?

更新

现在我将类从包1复制到包2,并且现在我正在创建该类的实例,我希望此实例指向存在于包1中的类,但当前它指向包1路径,如何修改它?

哦,所以我不能这样做:

Foo = new Foo() // pointing to Foo class in package 1
Foo = new Foo() // pointing to Foo class in package 2
4个回答

60

可以在多个包中拥有相同名称的两个类。但是,您不能在同一文件中使用两个import语句导入两个类。如果确实需要引用它们两个,则必须完全限定其中一个类名。


例如:假设您有

pkg1/SomeClass.java

package pkg1;
public class SomeClass {
}

pkg2/SomeClass.java

package pkg2;
public class SomeClass {
}

Main.java

import pkg1.SomeClass;   // This will...
import pkg2.SomeClass;   // ...fail

public class Main {
    public static void main(String args[]) {
        new SomeClass();
    }
}

如果您尝试编译,您将会得到:

$ javac Main.java
Main.java:2: pkg1.SomeClass is already defined in a single-type import
import pkg2.SomeClass;
^
1 error

然而,以下代码可以编译:

import pkg1.SomeClass;

public class Main {

    public static void main(String args[]) {
        new SomeClass();
        new pkg2.SomeClass();   // <-- not imported.
    }
}

在Java中,这是一个好的实践吗?还是建议避免使用这样的命名? - Ashutosh Singh
如果你控制两个包的代码,我会说这不是一个好的做法。一个例外是,如果你支持两个版本的模型,有com.company.model.v1.Catcom.company.model.v2.Cat,并且你正在实现一些需要引用两者的迁移代码。另一个例外是,如果你依赖于使用相同类名的多个外部库。 - aioobe
好的,那么当你遵循一些DDD和Clean Code的方法时呢?从这个角度来看,你更倾向于哪个优先(或者你更喜欢)?是Java的“不使用带有包名的类型”还是DDD/Clean Code的方法。就像在这里提到的那样:https://gist.github.com/cardil/b29a81efd64a09585076fe00e3d34de7#alternatives - Ashutosh Singh
1
所以,首先,过去的25年里我一直在Java中编程,而且只有一两次发现这是一个限制因素。我不确定领域驱动设计(DDD)和"clean code"在这里如何起作用。对我来说,“clean code”与“易于理解”的代码密切相关,如果你开始“重命名类”,老实说,我看不出这如何提高可理解性。在那些非常罕见的情况下,你必须处理同一文件中具有相同名称的两个类时,我可能更喜欢完全限定的名称,以确切指明我正在引用哪个类。 - aioobe
1
首先,我过去25年一直在使用Java进行编程,只有一两次发现这是一个限制因素。我不确定DDD和“清晰代码”在这里如何发挥作用。对我来说,“清晰代码”与“易于理解”的代码密切相关,如果你开始“重命名类”,我实在看不出这如何提高可理解性。在那些非常罕见的情况下,你必须在同一个文件中处理两个同名的类时,我可能更喜欢使用完全限定的名称,以确切地指明我所指的是哪个类。 - undefined
显示剩余2条评论

5
当然可以,但是当你在其他包中调用它们时,如果这两个都被包含在同一个源文件中,你需要区分哪一个。
回复评论:
com.test.package1.Foo myFoo = new com.test.package1.Foo();
com.test.package2.Foo myOtherFoo = new com.test.package2.Foo();

这是我的下一个问题,我该如何做到这一点?因为目前我正在调用它们,但代码引用的是包1类,而不是包2类。 - Rachel

3

当我遇到错误a type with the same simple name is already defined by the single-type-import时,谷歌将我带到了这个页面。经过很长时间的排查,我发现原来是这行代码 import com.sun.org.apache.xerces.internal.impl.dv.util.Base64; 悄悄地插入到了我的导入语句最顶部,而我原本想要导入的 import org.apache.commons.codec.binary.Base64; 却在导入语句底部。


在您的帮助下,我修复了类似的错误。我同时导入了“java.util.logging.Logger”和“org.slf4j.Logger”。不知何故,我忘记删除第一个。 - Razorfever

1

所以,我正在寻找比仅在实现的类中使用完全限定名称更智能的解决方案。

如果创建一个私有类,并扩展您的类,则可以自由地使用该类,而无需每次都编写完整的包名称。

包1

    namespace namespace1.Logger
    {
        public class Log
        {
            public void Foo1(){}
        }
    }

包裹2
    namespace namespace2.Logger
    {
        public class Log
        {
            public void Foo2(){}
        }
    }

我的类实现
    //using namespace1.Logger;
    //using namespace2.Logger;

    namespace MyProject
    {
        public class MyClass
        {
            public MyClass()
            {
                LoggerA a = new LoggerA();
                LoggerB b = new LoggerB();
                a.Foo1();
                b.Foo2();
            }

            private class LoggerA : namespace1.Logger.Log { }
            private class LoggerB : namespace2.Logger.Log { }
        }
    }

这是什么编程语言?问题是关于Java的。 - premek.v

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接