互联网上的大多数网站都说:
“使用
javac
命令编译.java
文件。然后使用java
命令运行它”
但是今天我试图在没有Java的情况下运行Java程序,但javac
结果却很奇怪。
以下是名为的文件的内容hello.java
:
public class Myclass {
public static void main(String[] args){
System.out.println("hello world");
}
}
Run Code Online (Sandbox Code Playgroud)
然后我跑了:
$ javac hello.java
Run Code Online (Sandbox Code Playgroud)
这给了我这个错误:
hello.java:1: error: class Myclass is public, should be declared in a file named Myclass.java
public class Myclass {
^
1 error
Run Code Online (Sandbox Code Playgroud)
但是,当我不使用javac
命令运行它时,它执行时没有任何错误。
$ java hello.java
hello world
Run Code Online (Sandbox Code Playgroud)
该java
命令还会编译程序吗?如果是,为什么我们需要该javac
命令?
我的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)
Run Code Online (Sandbox Code Playgroud)
kaa*_*aan 185
在Java 11之前,要运行代码,必须先对其进行编译,然后才能运行它。这是一个例子:
javac test.java
java test
Run Code Online (Sandbox Code Playgroud)
从Java 11开始,您仍然可以执行javac
+ java
,也可以单独运行java
以编译和自动运行代码。请注意,.class
将不会生成任何文件。这是一个例子:
java test.java
Run Code Online (Sandbox Code Playgroud)
如果运行java -help
,您将看到各种允许的用法。这是我的机器上的样子。最后一个是您遇到的问题:java [options] <sourcefile> [args]
它将“执行单个源文件程序”。
$ java -help
Usage: java [options] <mainclass> [args...]
(to execute a class)
or java [options] -jar <jarfile> [args...]
(to execute a jar file)
or java [options] -m <module>[/<mainclass>] [args...]
java [options] --module <module>[/<mainclass>] [args...]
(to execute the main class in a module)
or java [options] <sourcefile> [args]
(to execute a single source-file program)
Run Code Online (Sandbox Code Playgroud)
更新:
正如@BillK所指出的,OP还问:
为什么我们需要javac命令?
我们需要的原因javac
是创建.class
文件,以便可以像现在一样创建,测试,分发,运行,共享代码等。JEP 330的动机是使“学习Java的早期阶段以及编写小型实用程序时”变得更容易,而无需更改任何其他现有用法。
Eva*_*van 52
如果您运行的是Java 11,则有一项新功能允许单个源文件执行。在类名与文件名方面,单源编译器更加繁琐,因此您可以运行但无法成功编译。
如果您使用的是Java的早期版本,则由于编译错误(尤其是围绕类名的问题),您当前的hello.java无法编译。因此,绝对不可能调用java hello.java来编译您的代码,因为它不会编译。
似乎最有可能在执行java命令时运行了一些以前编译的代码。
是的,但不是您可能要说的那样。
当您使用javac
命令将.java文件编译为.class文件时,输出为字节码。字节码是基于Java虚拟机规范的理论CPU的机器代码(本机指令)。
该虚拟CPU规范是编写规范时常见的CPU类型的平均值。因此,它接近许多不同类型的CPU,从而使在多个CPU类型上运行相同的Java .class文件更加容易。
首次启动Java时,该java
命令将读取.class文件并一次解释一个字节码指令,然后将其映射到等效的本机指令,以了解其实际运行的CPU。这行得通,但并不是特别快。为了改善这一点,在Java运行时中添加了即时(JIT)编译。
使用JIT,该java
命令获取字节码,然后再次将其编译为运行该CPU的本机指令。现代Java运行时倾向于在后台进行JIT编译时开始解释字节码,并在就绪时切换到已编译的本机指令,还将分析正在运行的应用程序,然后使用不同的优化再次重新编译字节码,以获得最佳性能。
编辑(安抚失败的选民):
因此,在您的特定情况下(当您运行的是比v11更新的JRE时),代码将被编译(至少)两次