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

whi*_*hat 24 java directory package subdirectory

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

    package abraKadabra;

    public class SuperClass{
       protected int anInstance;

       public static void main(String [] abc){
           System.out.println("Hello");
       }
    }
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

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

Jon*_*eet 48

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

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

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

  • 请注意,虽然JLS允许这样做,但Eclipse不会:[错误16209 - 支持与目录位置不同的声明包](https://bugs.eclipse.org/bugs/show_bug.cgi?id=16209).所以如果你这样做,不要期望以后再使用Eclipse ...... (2认同)

whi*_*hat 7

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

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

    package mySample;


    public abstract class Sample{
        public static void main(String... a){
           System.out.println("Hello ambiguity");
        }
    }
Run Code Online (Sandbox Code Playgroud)

该文件位于"D:\ Code N Code\CommandLine"目录中.

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

    javac -d . Sample.java
Run Code Online (Sandbox Code Playgroud)

这会在我当前目录中自动创建"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
Run Code Online (Sandbox Code Playgroud)

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

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


cHa*_*Hao 5

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

但是,如果您的类使用包中的另一个类,出于同样的原因,您可能会在编译它时遇到问题(javac想要找到该类并确保它具有您的类使用的方法)。