是';java';命令编译Java程序?

是';java';命令编译Java程序?,java,javac,Java,Javac,互联网上的大多数网站都说: “使用javac命令编译.java文件。然后使用java命令运行它” 但是今天我尝试运行一个没有javac的java程序,结果很奇怪 下面是名为hello.java的文件的内容: public class Myclass { public static void main(String[] args){ System.out.println("hello world"); } } 然后我跑: $ javac hello.java 这给了我一个错误:

互联网上的大多数网站都说:

“使用
javac
命令编译
.java
文件。然后使用
java
命令运行它”

但是今天我尝试运行一个没有
javac
的java程序,结果很奇怪

下面是名为
hello.java
的文件的内容:

public class Myclass {
 public static void main(String[] args){
    System.out.println("hello world");
  }
}
然后我跑:

$ javac hello.java
这给了我一个错误:

hello.java:1: error: class Myclass is public, should be declared in a file named Myclass.java
public class Myclass {
       ^
1 error
但是,当我在没有
javac
命令的情况下运行它时,它执行时没有任何错误

$ java hello.java
hello world
java
命令是否也编译程序?如果是,为什么我们需要
javac
命令

my java的版本是:

openjdk version "12.0.2" 2019-07-16
OpenJDK Runtime Environment (build 12.0.2+10)
OpenJDK 64-Bit Server VM (build 12.0.2+10, mixed mode)

如果您运行的是Java 11,有一个新功能允许执行单个源文件。单源编译器在类名和文件名方面更加混乱,因此这就是您能够运行但无法成功编译的方式

如果您使用的是以前版本的Java,那么您当前的hello.Java不会编译,因为编译错误,特别是类名周围的错误。所以调用java hello.java绝对不可能编译代码,因为它不编译


在执行java命令时,您很可能正在运行一些以前编译过的代码

在Java 11之前,要运行代码,必须先编译代码,然后才能运行它。下面是一个例子:

javac test.java
java test
java test.java
自Java11以来,您仍然可以执行
javac
+
Java
,或者您可以自行运行
Java
来编译和自动运行代码。请注意,不会生成
.class
文件。下面是一个例子:

javac test.java
java test
java test.java
如果运行
java-help
,您将看到各种允许的用法。这是我的机器上的样子。最后一个是您遇到的:
java[options][args]
,它将“执行单个源文件程序”

$java-帮助
用法:java[options][args…]
(执行一个类)
或java[options]-jar[args…]
(执行jar文件)
或java[options]-m[/][args…]
java[选项]--模块[/][args…]
(在模块中执行主类)
或java[options][args]
(执行单个源文件程序)
更新:

正如@BillK所指出的,OP还提出了以下问题:

为什么我们需要javac命令


我们需要
javac
的原因是创建
.class
文件,这样代码就可以像今天一样被创建、测试、分发、运行、共享等等。其动机是使“学习Java的早期阶段以及编写小型实用程序时”变得更容易,而不改变任何其他现有用途。

是的,但不是你可能的意思

当您使用
javac
命令将.java文件编译成.class文件时,输出是一种称为字节码的东西。字节码是基于Java虚拟机规范的理论CPU的机器代码(本机指令)

这个虚拟CPU规范是在编写规范时常见的CPU类型的平均值。因此,它接近于许多不同类型的CPU,使得在多个CPU类型上运行相同的Java.class文件变得更容易

当Java第一次启动时,
Java
命令将读取.class文件,一次一个地解释字节码指令,然后将它们映射到它实际运行的CPU的等效本机指令。这很有效,但不是特别快。为了改进这一点,将JIT编译添加到Java运行时中

使用JIT时,
java
命令获取字节码,并将其再次编译为运行该字节码的CPU的本机指令。现代Java运行时倾向于在后台JIT编译时开始解释字节码,并在准备就绪时切换到编译的本机指令,还将评测正在运行的应用程序,然后以不同的优化重新编译字节码,以获得最佳性能

编辑(以安抚落选的选民):

因此,在您的特定情况下(当您运行比v11更新的JRE时),代码被编译(至少)两次

  • 作为单个.java文件转换为字节码
  • 通过JIT编译器解释字节码(尽管对于helloWorld,它可能没有时间运行任何已编译的本机代码)

  • 要回答出现此错误的原因,文件的类名必须与文件的
    basename
    匹配

    对于传统的
    javac
    ,有两个选项可以让此代码工作<代码>java顺序:

  • 将类重命名为
    公共类Hello

  • hello.java
    重命名为
    myclass.java


  • java 11的
    java
    解释器不强制执行此要求。包含
    main
    的类可以有任何名称,只要它是文件中的第一个类。这主要是为了简化初学者的学习过程,并允许使用shebang()编写“java脚本”。

    您使用的是哪个版本?我认为他们在Java9中引入了Java控制台,这可能就是您所经历的。您需要将类名与其文件名匹配—这是Java标准。只需将文件名更改为
    Myclass.java
    ,然后从命令行像这样编译
    javacmyclass.java
    ,然后像这样运行
    javamyclass
    。是的,
    javac
    仍然用于编译,如果您不想部署源代码,或者您有多个文件(对于源文件选项,
    java
    :仅用于启动单个源文件程序。)@Matthieu“java-version”的输出为:openjdk version“12.0.2”2019-07-16 openjdk运行时环境(build 12.0)。