包名称与文件夹结构不同,但Java代码仍然编译

我正在使用Notepad ++编写我的Java代码和命令提示符来编译和运行它。 以下是我的示例Java代码,

package abraKadabra; public class SuperClass{ protected int anInstance; public static void main(String [] abc){ System.out.println("Hello"); } } 

但是,此文件位于以下文件夹结构中:

“usingprotected \ superPkg”(usingProtected是C中层次结构中的某个文件夹:)

所以,我的包名在这里应该像usingProtected.superPkg而不是我编写的abraKadabra。

但是,当我从命令提示符编译这个Java代码时,它编译得很好,没有错误或警告。 为什么会这样? 软件包名称是否应该遵循文件夹结构? 如果它应该,它会如何坚持?

例如,如果我的包名是usingProtected.superPkg,编译器将以相反的顺序检查。 目前的工作目录应该是superPkg,那么父目录应该是使用保护并完成它。 它是如何用包名检查文件夹结构的?

Java语言规范不强制文件位于某个目录中。 它可选地允许编译器要求公共类位于具有相同类的名称的文件中,但我认为对于包没有任何类似的东西。 第7.2.1节讨论了文件系统中可能的存储选项,但据我所知,它没有说明有关强制执行源代码结构的任何内容。

但是,最佳实践 – 以及几乎普遍接受的约定 – 在源目录结构中反映包结构……并且javac 使用它来尝试查找未明确指定要编译的源文件。

请注意,如果从命令行进行编译,默认情况下每个类将出现在与相应源文件相同的位置,但如果使用“-d”选项(例如“-d bin”),编译器将构建适合您的输出目录结构,以指定目录为根。

经过一番实验后,我找到了如何使用包名并从命令提示符运行Java类文件的方法。

假设以下是我的Java源文件: –

  package mySample; public abstract class Sample{ public static void main(String... a){ System.out.println("Hello ambiguity"); } } 

该文件位于“D:\ Code N Code \ CommandLine”目录中。

现在,使用以下命令编译源代码(通过从cmd转到上面的目录): –

  javac -d . Sample.java 

这会在我当前目录中自动创建“mySample”文件夹。 因此,我的类文件Sample.class出现在目录“D:\ Code N Code \ CommandLine \ mySample”中。 编译器从我在源代码中给出的包名创建了这个新文件夹“mySample”。

因此,如果我将包名称命名为“package com.mySample”,编译器将创建两个目录并将我的类文件放在“D:\ Code N Code \ CommandLine \ com \ mySample”中。

现在,我仍在目前的工作目录中,即在“D:\ Code N Code \ CommandLine”中。 要运行我的类文件,我给出以下命令:

  java mySample.Sample 

所以,我给出了包的完整层次结构,然后是类名。 Java解释器将在当前目录中搜索“mySample”目录,并在其中搜索“Sample.class”。 它做对了并成功运行它。 🙂

现在,当我问为什么它编译我错误的包源代码时,它会成功编译代码,但是当我运行我的类文件时它会给出NoClassDefFoundError。 因此,上述方法可用于从命令行使用包名称。

如果您正在编译单个类,那么javac不需要在其他地方查找它。 它只是按原样编译文件,并将生成的.class放入同一个文件夹中。 但是,您通常无法使用该类,直到将其放入类路径中某个目录中的“abraKadabra”目录中。

但是,如果你的类在包中使用了另一个类,那么你可能会在编译它的地方遇到问题,原因相同( javac希望找到这个类并确保它有类和你的类使用的方法)。

Java编译器在编译源文件时不检查目录结构。 如您所述,假设您有一个以该指令开头的源文件

 package abraKadabra; 

您可以编译该文件,即使它不包含在子目录… / abraKadabra中。 如果源文件不依赖于其他包,则它将编译时没有错误。 但是,生成的程序将无法运行。 尝试运行该程序时,虚拟机将找不到生成的类。