使用 javac 与 java ClassName.java 编译和 运行 java 有不同的结果

Compiling and running java with javac vs java ClassName.java has different results

使用的java版本如下:

java 17.0.3 2022-04-19 LTS
Java(TM) SE Runtime Environment (build 17.0.3+8-LTS-111)
Java HotSpot(TM) 64-Bit Server VM (build 17.0.3+8-LTS-111, mixed mode, sharing)

class的命名为:Test2.java(内容如下:)

import java.util.Random;

public class B {

    public static final void main(String[] args) {
        System.out.println(new Random().nextInt(10));
    }

}


public class T2 {

    public static void main(String[] args) {
        System.out.println("This from another function");
    }

}

困惑:

以下命令 运行 在尝试编译时完全不同或 运行 class:

  1. 使用 java Test2.java 结果是一个随机整数(如代码所示)。
  2. javac Test2.java 编译失败。这正是我最初对命令 1 的期望。但是,它并没有那样发生。

思考过程: 根据我的所有经验,我了解到应该只有一个 public 顶级 class 并且 public class 的名称应该与文件名相同。在这种情况下,Test2.java 文件应该包含一个名为 Test2 的 class。但我特意创建了两个顶级 public classes none 其中包含文件的 class 名称。

真题: 为什么 command1 运行s 并找到第一个 class 的主要方法并打印该语句,尽管它一开始不应该编译。 Command2 按预期工作。为什么会出现差异?

the spec for the java command

中以这种方式记录

In source-file mode, the effect is as though the source file is compiled into memory, and the first class found in the source file is executed.

至于为什么这样设计我只能推测,因为我不为 Oracle 工作。但是,运行 针对文件的命令的结果不应该取决于文件的名称似乎是合理的。

让您 运行 适合单个文件的程序的 source-file mode 与正常的编译/执行过程有点不同。特别是:

In source-file mode, the effect is as though the source file is compiled into memory, and the first class found in the source file is executed.

  • No other source files are found and compiled, as if the source path is set to an empty value.
  • . . .
  • The source file is compiled in the context of an unnamed module.
  • The source file should contain one or more top-level classes, the first of which is taken as the class to be executed.
  • The compiler does not enforce the optional restriction defined at the end of JLS 7.6, that a type in a named package should exist in a file whose name is composed from the type name followed by the .java extension.

这些更改大概是为了更方便地在单个 .java 文件中包含完整的程序。