1. 概述
本教程将介绍javac工具,并描述如何使用它来将Java源文件编译成类文件。
我们将从javac命令的简短描述开始,然后通过查看它的各种选项来更深入地研究该工具。
2. javac命令
我们可以在执行javac工具时指定选项和源文件:
javac [options] [source-files]
其中[options]表示控制工具操作的选项,[source-files]表示要编译的一个或多个源文件。
所有选项实际上都是完全可选的。源文件可以直接指定为javac命令的参数或保存在引用的参数文件中,如之后所述。请注意,源文件应排列在与它们包含的类型的完全限定名称相对应的目录层次结构中。
javac的选项分为三组:标准、交叉编译和额外。在本文中,我们将重点介绍标准选项和额外选项。
交叉编译选项用于针对不同于编译器环境的JVM实现编译类型定义的不太常见的用例,并且不会被解决。
3. 类定义
让我们首先介绍我们将用来演示javac选项的类:
public class Data {
List<String> textList = new ArrayList();
public void addText(String text) {
textList.add(text);
}
public List getTextList() {
return this.textList;
}
}
源代码位于文件cn/tuyucheng/taketoday/javac/Data.java中。
请注意,我们在本文中使用*nix文件分隔符;在Windows机器上,我们必须使用反斜杠(‘\‘)而不是正斜杠(‘/’)。
4. 标准选项
javac命令最常用的标准选项之一是-d,它指定生成的类文件的目标目录。如果类不是默认包的一部分,则会创建反映包名称的目录结构以保留该类的类文件。
让我们在包含上一节中提供的结构的目录中执行以下命令:
javac -d javac-target cn/tuyucheng/taketoday/javac/Data.java
javac编译器将生成类文件javac-target/cn/tuyucheng/taketoday/javac/Data.class。请注意,在某些系统上,javac不会自动创建目标目录,在本例中为javac-target。因此,我们可能需要手动执行此操作。
以下是其他几个常用选项:
- -cp(或-classpath,–class-path):指定在哪里可以找到编译我们的源文件所需的类,如果缺少此选项并且未设置CLASSPATH环境变量,则使用当前工作目录(如上例中的情况)。
- -p(或–module-path):指示必要应用程序模块的位置,此选项仅适用于Java 9及更高版本-有关Java 9模块系统的指南,请参阅本教程。
如果我们想知道编译过程中发生了什么,例如加载了哪些类,编译了哪些类,我们可以应用-verbose选项。
我们将介绍的最后一个标准选项是参数文件。我们可以将参数存储在参数文件中,而不是直接将参数传递给javac工具。然后,这些文件的名称(以“@”字符为前缀)用作命令参数。
当javac命令遇到以’@’开头的参数时,它将以下字符解释为文件路径并将文件的内容扩展到参数列表中。空格和换行符可用于分隔此类参数文件中包含的参数。
假设我们在javac-args目录中有两个文件,名为options和types,内容如下:
options文件:
-d javac-target
-verbose
types文件:
cn/tuyucheng/taketoday/javac/Data.java
我们可以像以前一样编译Data类,并通过执行以下命令在控制台上打印详细信息:
javac @javac-args/options @javac-args/types
除了将参数保存在单独的文件中,我们还可以将它们全部存储在一个文件中。
假设在javac-args目录下有一个名为arguments的文件:
-d javac-target -verbose
cn/tuyucheng/taketoday/javac/Data.java
让我们将此文件提供给javac以获得与之前两个单独文件相同的结果:
javac @javac-args/arguments
请注意,我们在本节中介绍的选项只是最常见的选项。有关标准javac选项的完整列表,请查看此参考资料。
5. 额外选项
javac的额外选项是非标准选项,特定于当前的编译器实现,将来可能会更改。因此,我们不会详细讨论这些选项。
但是,有一个非常有用且值得一提的选项-Xlint。有关其他javac额外选项的完整描述,请访问此链接。
-Xlint选项允许我们在编译期间启用警告,有两种方法可以在命令行上指定此选项:
- -Xlint-触发所有推荐的警告
- -Xlint:key[,key]*–启用特定警告
以下是一些最方便的-Xlint键:
- rawtypes:警告原始类型的使用
- unchecked:对未经检查的操作发出警告
- static:警告从实例成员访问静态成员
- cast:警告不必要的强制转换
- serial:警告没有serialversionUID的可序列化类
- fallthrough:警告在switch语句中的失败
现在,在javac-args目录中创建一个名为xlint-ops的文件,内容如下:
-d javac-target
-Xlint:rawtypes,unchecked
cn/tuyucheng/taketoday/javac/Data.java
运行此命令时:
javac @javac-args/xlint-ops
我们应该看到原始类型和未经检查的警告:
cn/tuyucheng/taketoday/javac/Data.java:7: warning: [rawtypes] found raw type: ArrayList
List<String> textList = new ArrayList();
^
missing type arguments for generic class ArrayList<E>
where E is a type-variable:
E extends Object declared in class ArrayList
cn/tuyucheng/taketoday/javac/Data.java:7: warning: [unchecked] unchecked conversion
List<String> textList = new ArrayList();
^
required: List<String>
found: ArrayList
...
6. 总结
本教程介绍了javac工具,展示了如何使用选项来管理典型的编译过程。
实际上,我们通常使用IDE或者构建工具来编译程序,而不是直接依赖javac。但是,对该工具的深入了解将使我们能够在高级用例中自定义编译。
与往常一样,本教程的完整源代码可在GitHub上获得。