1. Overview
1.概述
In this tutorial, we’re going to learn how we can interact with the Java compiler through the command-line interface.
在本教程中,我们将学习如何通过命令行界面与Java编译器互动。
As a prerequisite, we need to have Java downloaded and the JAVA_HOME environment variable configured in our machine.
作为先决条件,我们需要下载Java,并在我们的机器中配置JAVA_HOME环境变量。
2. Compiling a Single Java Source Code File
2.编译单个Java源代码文件
Java provides a simple tool – javac to compile java source code files. Let’s start with compiling a small class, Car.java:
Java提供了一个简单的工具–javac来编译java源代码文件。让我们从编译一个小类开始,Car.java。
public class Car {
private String make;
private String model;
// standard setters and getters
}
We can compile this from a single command within the directory where this file is located:
我们可以在这个文件所在的目录中用一个命令来编译这个文件。
javac Car.java
If everything works without error, there will be no output. The compiler will create the Car.class, which contains the bytecode, in the current working directory.
如果一切顺利,没有错误,就不会有输出。编译器将在当前工作目录中创建包含字节码的Car.class,。
3. Compiling Multiple Source Code Files
3.编译多个源代码文件
Usually, our programs use more than a single class file. Let’s now see how we can compile a simple program with multiple classes.
通常情况下,我们的程序会使用不止一个类文件。现在让我们看看如何编译一个有多个类的简单程序。
First, let’s add two new types, Owner.java and History.java:
首先,让我们添加两个新类型,Owner.java和History.java。
public class Car {
private String make;
private String model;
private Owner owner;
private History history;
}
public class Owner {
private String name;
}
public class History {
private String details;
}
Now, we need to run the below command to compile:
现在,我们需要运行下面的命令来进行编译。
javac Owner.java Car.java History.java
We should note that since the classes used by the Car class are in the same directory, it’s actually optional whether we specify them. We could still just compile Car.java.
我们应该注意到,由于Car类所使用的类都在同一个目录中,所以我们是否指定它们实际上是可选的。我们仍然可以直接编译Car.java。
4. Essential Java Compiler Options
4.基本的Java编译器选项
So far, we have just used the javac command without any extra options by just passing our class names as parameters. However, we can also customize it. We can tell the java compiler where to find classes of our libraries, the base path where our code resides, and where to generate the eventual result.
到目前为止,我们只是使用了javac命令,没有任何额外的选项,只是将我们的类名作为参数传递。然而,我们也可以对它进行定制。我们可以告诉java编译器在哪里找到我们的库的类,我们的代码所在的基本路径,以及在哪里生成最终的结果。
Let’s take a closer look at some of these options.
让我们仔细看看其中的一些选择。
- -cp or -classpath
- -sourcepath
- -d (directory)
4.1. What Is the -cp or -classpath Option?
4.1.什么是-cp或-classpath选项?
Using the classpath, we can define a set of directories or files such as *.jar, *.zip that our source code depends on during compilation. Alternatively, we can set the CLASSPATH environment variable.
使用classpath,我们可以定义一组目录或文件,如*.jar、*.zip,我们的源代码在编译时依赖于这些文件。或者,我们可以设置CLASSPATH环境变量。
We should note that the classpath option has higher precedence than the environment variable.
我们应该注意,classpath选项比环境变量有更高的优先权。
If none of them are specified, then the classpath is assumed to be the current directory. When we wish to specify multiple directories, the path separator is ‘:‘ for most operating systems except Windows, where it’s ‘;‘.
如果它们都没有被指定,那么classpath就被认为是当前目录。当我们希望指定多个目录时,大多数操作系统的路径分隔符是’:‘,Windows除外,它是’;‘。
4.2. What Is the -sourcepath Option?
4.2.什么是-sourcepath选项?
This option makes it possible to specify the top directory where all of our source code that needs compilation resides.
这个选项使得我们可以指定所有需要编译的源代码所在的顶级目录。
If not specified, the classpath gets scanned for the sources.
如果不指定,将扫描classpath以获取源。
4.3. What Is the -d Option?
4.3.什么是-d选项?
We use this option when we want to have all compiled results in one place, separate from the source code. We need to keep in mind that the path we want to specify must exist beforehand.
当我们想把所有的编译结果放在一个地方,与源代码分开时,我们就使用这个选项。我们需要记住,我们想要指定的路径必须事先存在。
During compilation, this path is used as a root directory, and sub-folders are created automatically according to the package structure of the classes. If this option is not specified, every single *.class file is written next to their corresponding source code *.java file.
在编译过程中,这个路径被用作根目录,并根据类的包结构自动创建子文件夹。如果不指定这个选项,每一个*.class文件都会写在它们对应的源代码*.java文件旁边。
5. Compiling With an External Library
5.使用外部库进行编译
Besides the classes we create, we also need to use external libraries in our programs. Let’s now take a look at a more complex example:
除了我们创建的类,我们还需要在我们的程序中使用外部库。现在让我们来看看一个更复杂的例子。
libs/ ├─ guava-31.1-jre.jar model/ ├─ Car.java ├─ History.java ├─ Owner.java service/ ├─ CarService.java target/
Here, we’ve organized our classes into packages. Additionally, we’ve introduced the target and the libs directories to place compiled results and libraries, respectively.
在这里,我们将我们的类组织成包。此外,我们还引入了target和libs目录,分别用来放置编译的结果和库。
Let’s say we want to use the ImmutableSet class provided by the Guava library. We download and place it under the libs folder. Then, under the service package, we introduce a new class that uses the external library in CarService.java:
假设我们想使用Guava库所提供的ImmutableSet类。我们下载并将其放置在libs文件夹下。然后,在service包下,我们引入一个新的类,在CarService.java中使用该外部库。
package service;
import model.Car;
import java.util.Set;
import com.google.common.collect.ImmutableSet;
public class CarService {
public Set<Car> getCars() {
Car car1 = new Car();
Car car2 = new Car();
ImmutableSet<Car> cars = ImmutableSet.<Car>builder()
.add(car1)
.add(car2)
.build();
return cars;
}
}
Now, it’s time to compile our project:
现在,是时候编译我们的项目了。
javac -classpath libs/*:. -d target -sourcepath . service/CarService.java model/*.java
We’ve included the libs folder in our classpath with -cp.
我们已经用-cp将libs文件夹纳入我们的classpath。
libs/ ├─ guava-31.1-jre.jar model/ ├─ Car.java ├─ History.java ├─ Owner.java service/ ├─ CarService.java target/ ├─ model/ │ ├─ Car.class │ ├─ History.class │ ├─ Owner.class ├─ service/ │ ├─ CarService.class
As we can see, javac successfully resolved the external ImmutbleSet class and placed the compiled classes in the target folder.
我们可以看到,javac成功地解析了外部的ImmutbleSet类,并将编译后的类放在target文件夹中。
6. Conclusion
6.结语
In this article, we learned how we could compile multiple source code files even when we have dependencies on external libraries.
在这篇文章中,我们了解到,即使我们对外部库有依赖性,我们也可以编译多个源代码文件。
Additionally, we took a quick look at some essential options that we can take advantage of during complex compilation tasks.
此外,我们快速浏览了一些必要的选项,在复杂的编译任务中我们可以利用这些选项。