Java包结构与文件夹结构

Java包结构与文件夹结构,java,package,structure,Java,Package,Structure,我所看到的所有Java项目都使用一个遵循包结构的文件夹结构。这将导致大量不包含任何文件的文件夹 例如,包以com.mydomain.mysystem.myutility开头。这将导致文件夹src\com,src\com\mydomain,src\com\mydomain\mysystem不包含任何文件。很可能myutility也只包含文件夹 很可能还有一个项目文件夹包含名称myutility,因此完整的文件夹路径可能是myutility\src\main\java\com\mydomain\my

我所看到的所有Java项目都使用一个遵循包结构的文件夹结构。这将导致大量不包含任何文件的文件夹

例如,包以
com.mydomain.mysystem.myutility
开头。这将导致文件夹
src\com
src\com\mydomain
src\com\mydomain\mysystem
不包含任何文件。很可能
myutility
也只包含文件夹

很可能还有一个项目文件夹包含名称
myutility
,因此完整的文件夹路径可能是
myutility\src\main\java\com\mydomain\mysystem\myutility\otherfolder

这种做法非常普遍,但它让我们怀疑它有多有用。与不创建这些额外文件夹的情况相比,有什么好处?例如使用
myutility\src\main\java\otherfolder

它似乎同样有效,但它为每个人节省了额外的导航步骤。我可以用这两种方法编译Java源文件

在一个项目中,通常所有源代码都位于
com\mydomain\mysystem
中。在所有项目中放置这些“空”文件夹有什么好处

我要澄清的是,我并不是在质疑包结构的有用性。马文也很清楚


问题是为什么我们在整个组织的存储库中使用通常相同的空文件夹

这样做的原因是为了防止冲突并确保类可以唯一标识。这意味着,如果两个类具有相同的名称,则仍然可以通过不同的导入加载它们

做到这一点最安全的方法是使用域名,因为域名的性质是唯一的:

com.google.
例如

您的方法可以工作并保存一些空文件夹,但不可扩展。

源(和类)文件是这样组织的,以便Java编译器(和运行时环境)可以找到它们

当Java编译器编译您的类时,它需要您的类所依赖的每个类的源文件或类文件,以便它可以检查该类是否存在,是否使用正确的参数调用了所有方法等。此外,如果它找到了源文件而不是类文件,或者该类文件比源文件旧,它将编译您使用的类的源文件

编译器当然可以只检查类路径的所有子文件夹,甚至整个磁盘,但这将花费大量时间。由于这种约定,编译器只需为每个类路径条目检查一个子文件夹。当然,你可以想出不同的解决方案,但是(当时)Sun公司的人认为这是最好的选择

当然,上述内容也适用于在运行时加载的类文件,因此类文件也存储在类似的文件夹结构中


还请注意,Java应用程序和库通常打包为Jar文件(基本上是一个内部具有相同文件夹结构的zip文件),因此在许多情况下,它们在文件系统中显示为单个文件。

也许这个答案会让人明白一些:相信我,这比您必须自己管理的替代方案要好。使用
make
和friends做了25年,再也没有了。当所有源文件(请记住,这里所有的问题都是源文件)都有相同的前缀时,它的伸缩性很好。NET中的约定是源层次结构的“根”目录代表一个特定的名称空间,并为其中的“子名称空间”添加目录。工作非常好。是的,绝对-因为您通常不会将第三方库与源代码放在一起,是吗?请记住,这并不意味着改变包名,只是改变源文件的布局。为什么使用第三方库会影响这一点?区分“完全限定名”和“源文件的文件夹层次结构”非常重要。讨论的源文件布局(
myutility\src\main\java\otherfolder
)是一个包更改,该布局唯一有效的Java包是
otherfolder
,因为其他所有内容都会导致编译错误:
package x不对应于文件路径y
。如果您使用的编译器确实执行了该规则(据我所知,JLS中没有),那么这就是您的选择。就我个人而言,我认为这是一个遗憾——我肯定更喜欢.NET方法。啊,我明白了,这是有道理的。谢谢你提供的信息。或者编译器可以只得到它应该编译的所有东西的文件名——就像在许多其他情况下发生的那样…@JonSkeet是的,正如我在回答中所写的,存在其他可能性。我认为文件夹结构方案对于查找编译的类文件更有意义,因此,对于源文件不使用完全不同的方案是有意义的。实际上,这一切并不重要,因为IDE管理Java源文件的文件夹结构,以及为其他语言提供给编译器的源代码列表。