构建 Java 源文件、and/or declaring/importing 包以确保无错误编译的规则是什么?

What are the rules for structuring Java source files, and/or declaring/importing packages to ensure error-free compilation?

我有几个文件保存在一个包中,customQ。此包被导入到名为 QWithExceptions 的测试客户端中。源码树排列如下:

/tryThis09_01/+
              |
              -QWithExceptions.java
              |
              /customQ/+
                       |
                       -circularQ.java
                       -staticQ.java
                       -emptyQException.java
                       -fullQException.java

当我cdtryThis09_01/和运行$javac QWithExceptions.java.

时,测试客户端编译没有错误

但是,当我决定进行一些试验时,我发现我对包及其结构的直觉完全错误。实际的包 customQ 和测试客户端 QWithExceptions 更深地埋在源代码树中,如下所示:

~/learningJava/beginnersGuide/chapter09/tryThis09_01/+
                                                     |
                                                     -QWithExceptions.java
                                                     |
                                                     /customQ/+
                                                              |
                                                              -circularQ.java
                                                              -staticQ.java
                                                              -emptyQException.java
                                                              -fullQException.java

我的开发环境中的 linter 建议我将 customQ/*.java 中的包声明从 package customQ; 更改为 package beginnersGuide.chapter09.tryThis09_01.customQ;。这样做之后,我更改了测试客户端中的 import 语句以反映新的包名称并将 QWithExceptions.java 移动到 ~/learningJava/ 并执行 $javac QWithExceptions.java,这导致了一系列编译错误。

我还尝试了 $javac -cp .:$CLASSPATH QWithExcpetions.java$javac -d . -cp .:$CLASSPATH QWithExcpetions.java,以及将 QWithExceptions.java 在源代码树中一次一个目录地向上和向下移动,但都出现了各种错误。

目前,我正在努力解决 bad class file 错误。虽然我知道编译器希望我将有问题的文件移动到文件树中的其他位置(或者可能修改包声明或导入语句),但我不确定如何在不调用 package does not exist 错误的情况下执行此操作。

我确实遗漏了一些包编写的基本规则,这些规则(对我而言)不是从更广泛的网络或我的 Java 文本中发现的琐碎实现中立即显而易见的。如果你知道它是什么,请分享你的智慧。

我无法重现您的问题,因为您忘记显示错误消息和文件内容。但我可以告诉你它是如何工作的:

我的文件夹结构:

stefan@stefanpc:~/learningjava$ tree
.
├── beginnersGuide
│   └── chapter09
│       └── tryThis09_01
│           └── customQ
│               └── Test.java
└── Main.java

文件Test.java:

package beginnersGuide.chapter09.tryThis09_01.customQ;

public class Test
{
   public int i;
}

文件Main.java:

import beginnersGuide.chapter09.tryThis09_01.customQ.Test;

public class Main {
    
    Test test;

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

编译:

stefan@stefanpc:~/learningjava$ javac Main.java 
stefan@stefanpc:~/learningjava$ 

类 和相关文件名应以大写字符开头。但我认为这不是你的问题原因。

甲骨文的建议: https://docs.oracle.com/javase/tutorial/java/package/namingpkgs.html

Java 要求包声明与文件夹结构一致。例如,如果您在源文件的顶部声明了 package a.b.c',则需要将该路径放在 a/b/c 文件夹结构中。请注意,文件夹结构在编译期间是相对于源根目录的。因此,如果您的代码位于 'src' 文件夹中,并尝试从该 'src' 的父级上下文中编译,您将得到错误,因为文件夹结构看起来像 src/a/b/c 编译器.同样,如果您的编译上下文设置为文件夹 'a',您将收到错误,因为现在该文件夹对编译器来说看起来像 b/c

这是 Java 新用户的常见问题。它旨在让事情更容易找到,但可能会很烦人。