51

我是一个新手,刚刚了解到,如果我定义说

package my.first.group.here;
...

那么这个包中的Java文件将被放置在my/first/group/here目录下。

将一些 Java 文件放在一个包中的主要目的是什么?另外,如果我选择采用这个,我应该如何对它们进行分组?

谢谢


编辑:对于任何可能再次遇到相同问题的人,我刚刚在Sun的软件包上找到了本教程。

4

11 回答 11

41

让我们从Wikipedia 文章中描述的“Java 包”的定义开始:

Java 包是一种将 Java 类组织到命名空间中的机制,类似于 Modula 的模块。Java 包可以存储在称为 JAR 文件的压缩文件中,从而允许类作为一个组而不是一次下载一个更快。程序员通常还使用包来组织属于同一类别或提供类似功能的类。

因此基于此,Java 中的包只是一种用于组织类和防止类名冲突的机制。您可以随意命名它们,但 Sun 已经发布了一些命名约定,您应该在命名包时使用它们:

套餐

唯一包名的前缀总是用全小写的ASCII字母写的,应该是顶级域名之一,目前是com, edu, gov, mil, net, org,或者是英文的两字母代码之一识别 ISO 标准 3166, 1981 中指定的国家/地区。

包名称的后续组成部分根据组织自己的内部命名约定而有所不同。此类约定可能会指定某些目录名称组件是部门、部门、项目、机器或登录名。

例子:

  • com.sun.eng

  • com.apple.quicktime.v2

  • edu.cmu.cs.bovik.cheese

于 2009-07-06T18:30:20.843 回答
14

我是一个大型应用程序,您肯定有两个名称完全相同的文件(java.util.Date 和 java.sql.Date),尤其是当您开始引入第三方 jar 时。所以基本上,你可以使用包来确保唯一性。

最重要的是,在我看来,打包将项目分解为有意义的部分。所以我的 SQL 包有 sql 相关的代码,而我的 logger 包处理日志。

于 2009-07-06T18:31:20.653 回答
5

除了其他答案中提到的命名空间之外,您还可以根据在该成员上声明的范围限制对方法和字段的访问。具有公共范围的成员可以自由访问,为了限制访问,您通常将它们定义为私有(即隐藏在类之外)。您还可以使用受保护范围来限制对类型及其子项的访问。还有一个默认范围(没有限定符的成员具有默认范围),它允许同一包中的子类型和类型访问该成员。这可以是共享字段和方法的有效方式,而不会使它们过于广泛可用,并且可以帮助进行测试。

例如,下面的方法将对同一包的所有其他成员可见。

public class Foo {
    int doSomething() {
        return 1;
    }
}

要测试该方法,您可以在同一个包中定义另一种类型(但可能是不同的源位置),该类型将能够访问该方法。

public class FooTest {
    @Test
    int testDoSomething() {
        Foo foo = new Foo();
        assertEquals(1, foo.doSomething());
    }
}
于 2009-07-06T20:00:26.947 回答
4

它允许程序由多个不同的程序/组件/库组成,这样它们的类名不会冲突,组件更容易组织。请参阅http://java.sun.com/docs/books/tutorial/java/package/index.html

在 Java 中,习惯上将包命名为反向域名。例如,如果您公司的域是“initech.com”并且您正在制作一个名为“Gizmo”的程序,则包名称通常以“com.initech.gizmo”为前缀,并带有用于该程序不同组件的子包。

于 2009-07-06T18:29:29.067 回答
2

包对于提供类分离的灵活性很重要。它们可用于:

  • 分离项目
  • 分离模块
  • 分离应用层(业务、Web、DAO)
  • 更细粒度的代码分离

例如

com.mycompany.thisproject.thismodule.web

可以指示某些模块的 web 层。

于 2009-07-06T18:31:07.207 回答
2

归根结底,我们想要在 Java 中使用包有 3 个核心原因。

1)更容易维护

组织classespackages遵循通过封装分离关注点的原则,并允许在整个系统设计中更好的凝聚力。进一步,按功能打包允许开发人员团队找到相关的类和接口以进行更改,支持垂直切片技术用于敏捷方法中使用的缩放方法。有关更多信息,请参阅博客文章:按功能而不是按层编码打包您的类:按垂直切片打包

2)提供包安全

包只允许外部访问public包含类中方法的访问修饰符。使用protectedor no 修饰符只能被同一包中的类访问。有关更多信息,请参阅帖子: 哪个 Java 访问修饰符允许仅由其他包中的子类访问成员?

3)避免类似的命名

与 .NET 的命名空间类似,类名包含在其包含包的范围内。这意味着两个互斥的包可以包含同名的类。这是因为包本身有不同的名称,因此完全限定的名称也不同。有关详细信息,请参阅教程 [命名包:Java 教程][3]。

于 2017-06-17T03:22:31.660 回答
0

关于包的另一个重要的事情是访问控制的受保护成员。

受保护的介于公共(每个人都可以访问)和私有(只有类内部可以访问)之间。标记为受保护的事物可以从同一个包或子类中访问。这意味着对于受限访问,您不必将所有内容放在同一个类中。

于 2009-07-06T19:08:51.543 回答
0

从关于该主题的维基百科页面:

“Java 包是一种将 Java 类组织到类似于 Modula 模块的命名空间的机制。Java 包可以存储在称为 JAR 文件的压缩文件中,从而允许类作为一个组而不是一次一个地下载更快。程序员通常也使用包来组织属于同一类别或提供类似功能的类。”

于 2009-07-06T18:29:01.127 回答
0

另外,如果我选择采用这个,我应该如何对它们进行分组?

这在很大程度上取决于您将在项目中采用的设计模式。在大多数情况下(特别是,如果您是新手),您会希望按功能或其他一些逻辑相似性对它们进行分组。

于 2009-07-06T18:31:52.617 回答
0

Java 的实现非常精确。它并没有真正为捏造留下空间。

如果每个人都使用相同的包,他们将不得不找到某种“全球通用”的方式来确保没有两个类名发生冲突。

这让每一个曾经编写过的类都适合自己的“地方”,如果你不想看,你就不必看。

您可能在系统的 4 个不同位置定义了不同的“Point”对象,但您的类将只使用您期望的那个(因为您导入了那个)。

他们确保每个人都有自己的空间的方式是使用你的反向域,所以我的是“tv.kress.bill”。我拥有该域--实际上我与我的兄弟“tv.kress.doug”共享它,即使我们共享同一个域,我们也不会发生冲突。

如果您公司的一百个部门都使用 Java 开发,那么他们可以在没有冲突的情况下这样做,并且确切地知道如何划分它。

不进行这种划分的系统现在对我来说似乎很不稳定。我可能会使用它们来编写一个用于个人内容的脚本,但是如果没有进行一些严格的打包,我会觉得开发任何大的东西会感到不舒服。

于 2009-07-06T18:36:51.373 回答
0

其他人提供了非常特定于 Java 的答案,这很好,但这里有一个类比:为什么要将文件组织到硬盘上的目录中?为什么不把所有东西都放在一个目录中的平面文件系统呢?

答案当然是包提供了组织。与数据库接口的程序部分与向用户显示 UI 的程序部分不同,因此它们将位于不同的包中。

与目录一样,它也提供了一种解决名称冲突的方法。您可以在几个不同的目录中拥有一个 temp.txt,就像您可以拥有两个出现在不同包中的类一样。这变得很重要(1)当您开始与互联网上的其他人组合代码时,或者(2)甚至意识到 Java 的类加载是如何工作的。

于 2009-07-06T19:03:10.853 回答