为什么 java 源文件需要包声明?

2022-09-02 20:27:55

我认为我无法理解java包结构,对我来说,java文件在其中有一个包声明似乎是多余的,然后还需要出现在与包名称匹配的目录中。例如,如果我有一个文件:MyClass.java

package com.example;

public class MyClass {
    public static void main(String[] args) {
        System.out.println("Hello, World");
    }
}

然后,我将被要求将此文件位于 相对于基目录的 中,并且我将从基目录执行以运行它。com/examplejava com.example.MyClass

为什么编译器不能通过查看目录结构来推断包名称?例如,如果我从基目录编译文件,我不明白为什么MyClass.java不会隐式属于包。javac com\example\MyClass.javacom.example

我知道有一个默认的包,但似乎源文件中的包声明是多余的信息吗?


答案 1

正如您(隐式)承认的那样,如果默认包,则不需要声明包的名称。让我们把这个小问题放在一边...

这种看似冗余的原因是,如果没有声明,Java1源代码的含义将是模棱两可的。例如,路径名为“/home/steve/project/src/com/example/Main.java”的源文件可以有 7 个不同的完全限定名,具体取决于您编译代码的方式。最有可能的是,其中只有一个是“正确”的。但是,您无法通过查看(仅)一个源文件来判断哪个FQN是正确的。package


还应该注意的是,Java语言规范不要求您根据包来组织源代码树。这是一个(大型)Java编译器家族的要求,但是可以编写一个不需要这样做的一致性编译器。例如:

  • 源代码可以保存在数据库中。
  • 源代码可以保存在具有随机文件名2 的文件树中。

在这种情况下,声明不会重复文件路径名或(必然)任何内容。但是,除非存在一些冗余,否则为类找到正确的源“文件”对于编译器来说将是昂贵的......对程序员来说有问题。package

上述注意事项是大多数 Java 工具链依赖于文件树结构来查找源类和编译类的实际原因。


1 - 我的意思是Java的假设方言,不需要声明。
2 - 编译器需要扫描文件树以查找所有Java文件,并解析它们以确定哪个文件定义了哪个类。可能,但不是很实用。


答案 2

把问题转到头上:

假设 package 语句是重要的事情 - 它表示类的命名空间并属于类文件。

所以现在的问题是 - 为什么类必须位于与其包匹配的文件夹中?

答案是,它使找到它们变得更加容易 - 这只是组织它们的好方法。

这有帮助吗?


推荐