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

时间:2011-12-06 05:52:01

标签: java package directory subdirectory

我正在使用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,那么父目录应该是useProtected并完成它。它是如何用包名检查文件夹结构的?

4 个答案:

答案 0 :(得分:48)

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

然而,最佳实践 - 以及一个非常普遍接受的约定 - 反映源目录结构中的包结构......并且javac 使用它来尝试查找源文件明确指定编译。

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

答案 1 :(得分:6)

经过实验,我找到了如何使用包名并从命令提示符运行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。因此,上述方法可用于从命令行使用包名称。

答案 2 :(得分:4)

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

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

答案 3 :(得分:0)

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

开头的源文件
package abraKadabra;

即使文件未包含在子目录中,您也可以编译该文件... / abraKadabra。如果源文件不依赖于其他包,则它将编译时没有错误。但是,生成的程序将不会运行(除非还包括执行中的包名称)。尝试运行程序时,虚拟机将找不到生成的类。