官网地址:javac
欢迎关注留言,我是收集整理小能手,工具翻译,仅供参考,笔芯笔芯.
您可以使用该javac
工具及其选项来读取 Java 类和接口定义,并将它们编译为字节码和类文件。
概要
javac [options] [sourcefiles]
options
命令行选项。请参阅javac 选项概述。
sourcefiles
要编译(例如MyClass.java
)或处理注释(例如MyPackage.MyClass
)的一个或多个源文件。
描述
该javac
命令读取用 Java 编程语言编写的类和接口定义,并将它们编译为字节码类文件。该javac
命令还可以处理 Java 源文件和类中的注释。
JDK 9 中引入了启动器环境变量JDK_JAVAC_OPTIONS
,它将其内容添加到命令行中javac
。请参阅使用 JDK_JAVAC_OPTIONS 环境变量。
有两种方法将源代码文件名传递给javac
.
对于少量源文件,可以在命令行中列出文件名。
对于大量源文件,可以使用命令行上的选项来包含列出源文件名的文件。有关选项的说明,请参阅标准选项;有关参数文件的说明,请参阅javac 命令行参数文件。 @filename
javac
javac
源代码文件名必须有.java
后缀,类文件名必须有.class
后缀,源文件和类文件都必须有标识类的根名称。例如,一个名为 的类MyClass
将被写入名为 的源文件中MyClass.java
,并编译为名为 的字节码类文件MyClass.class
。
内部类定义会生成附加的类文件。这些类文件的名称由内部类名称和外部类名称组合而成,例如MyClass$MyInnerClass.class
.
您应该将源文件排列在反映其包树的目录树中。例如:
Oracle Solaris、Linux 和 macOS:如果所有源文件都位于 中/workspace
,则将源代码放入com.mysoft.mypack.MyClass
中/workspace/com/mysoft/mypack/MyClass.java
。
Windows:如果所有源文件都位于 中\workspace
,则将源代码放入com.mysoft.mypack.MyClass
中\workspace\com\mysoft\mypack\MyClass.java
。
默认情况下,编译器将每个类文件与其源文件放在同一目录中。您可以使用标准选项-d
中描述的选项指定单独的目标目录。
编程接口
该javac
命令支持由包中的类和接口定义的新 Java 编译器 API javax.tools
。
隐式加载的源文件
要编译一组源文件,编译器可能需要隐式加载其他源文件。请参阅搜索类型。此类文件目前不受注释处理。默认情况下,当发生注释处理并且编译任何隐式加载的源文件时,编译器会发出警告。该-implicit
选项提供了一种抑制警告的方法。
使用 JDK_JAVAC_OPTIONS 环境变量
环境变量的内容JDK_JAVAC_OPTIONS
以空格 ( ) 或空格字符(\n
、\t
、\r
或\f
)分隔,添加到javac
作为参数列表传递的命令行参数之前。
javac
环境变量的编码要求与系统上的命令行相同。JDK_JAVAC_OPTIONS
环境变量内容的处理方式与命令行中指定的方式相同。
单引号 ( '
) 或双引号 ( "
) 可用于括起包含空格字符的参数。只需删除一对引号即可保留开引号和第一个匹配的闭引号之间的所有内容。如果未找到匹配的引用,启动器将中止并显示错误消息。受命令行中指定的支持。但是,如 中所示,不支持使用通配符。 @files
@files
引用包含空格的参数的示例:
export JDK_JAVAC_OPTIONS='@"C:\white spaces\argfile"'
export JDK_JAVAC_OPTIONS='"@C:\white spaces\argfile"'
export JDK_JAVAC_OPTIONS='@C:\"white spaces"\argfile'
javac 选项概述
编译器具有当前开发环境支持的一组标准选项和交叉编译选项。编译器还有一组非标准选项,这些选项特定于当前虚拟机和编译器实现,但将来可能会发生变化。非标准选项以 开头-X
。javac
以下部分描述了 不同的选项集:
标准选项
javac 的交叉编译选项
额外选项
标准选项
@filename
从文件中读取选项和文件名。要缩短或简化javac
命令,您可以指定一个或多个包含javac
命令参数(-J
选项除外)的文件。这使您可以javac
在任何操作系统上创建任何长度的命令。请参阅javac 命令行参数文件。
-Akey[=value]
指定传递给注释处理器的选项。这些选项不会被javac
直接解释,但可供各个处理器使用。该key
值应该是一个或多个由点 ( . ) 分隔的标识符。
--add-modules module,module
指定除初始模块之外要解析的根模块,或者模块路径上的所有模块(如果module
是)ALL-MODULE-PATH.
--boot-class-path path
或者-bootclasspath path
覆盖引导类文件的位置。
笔记:
这只能在编译 JDK 9 之前的版本时使用。如果适用,请参阅 --release
、-source
、 或中的描述-target
以了解详细信息。
--class-path path
,, 或者-classpath path
-cp path
指定在哪里可以找到用户类文件和注释处理器。该类路径覆盖CLASSPATH
环境变量中的用户类路径。
如果未指定 --class-path
、-classpath
、 或,则用户类路径是当前目录。-cp
如果-sourcepath
未指定该选项,则还会在用户类路径中搜索源文件。
如果-processorpath
未指定该选项,则还会在类路径中搜索注释处理器。
-d directory
设置类文件的目标目录。如果类是包的一部分,则将javac
该类文件放入反映包名称的子目录中,并根据需要创建目录。例如:
Oracle Solaris、Linux 和 macOS:如果您指定-d
/home/myclasses
并且类名为com.mypackage.MyClass
,则类文件为/home/myclasses/com/mypackage/MyClass.class
.
Windows:如果您指定-d
C:\myclasses
并且类被调用com.mypackage.MyClass
,则类文件为C:\myclasses\com\mypackage\MyClass.class
.
如果-d
未指定该选项,则将javac
每个类文件放在与生成该类文件的源文件相同的目录中。
笔记:
该-d
选项指定的目录不会自动添加到您的用户类路径中。
-deprecation
显示对已弃用成员或类的每次使用或覆盖的描述。如果没有该-deprecation
选项,javac
则显示使用或覆盖已弃用的成员或类的源文件的摘要。该-deprecation
选项是 的简写-Xlint:deprecation
。
--enable-preview
启用预览语言功能。-source
与或结合使用--release
。
-encoding encoding
指定源文件使用的字符编码,例如 EUC-JP 和 UTF-8。如果-encoding
未指定该选项,则使用平台默认编码。
-endorseddirs directories
覆盖认可的标准路径的位置。
笔记:
这只能在编译 JDK 9 之前的版本时使用。如果适用,请参阅 --release
、-source
、 或中的描述-target
以了解详细信息。
-extdirs directories
覆盖已安装扩展的位置。该directories
变量是一个以冒号分隔的目录列表。将搜索指定目录中的每个 JAR 文件以查找类文件。找到的所有 JAR 文件都成为类路径的一部分。
如果您进行交叉编译,则此选项指定包含扩展类的目录。请参阅javac 的交叉编译选项。
笔记:
这只能在编译 JDK 9 之前的版本时使用。如果适用,请参阅 --release
、-source
、 或中的描述-target
以了解详细信息。
-g
生成所有调试信息,包括局部变量。默认情况下,仅生成行号和源文件信息。
-g:[lines, vars, source]
仅生成由逗号分隔的关键字列表指定的调试信息类型。有效的关键字是:
lines
行号调试信息。
vars
局部变量调试信息。
source
源文件调试信息。
-g:none
不生成调试信息。
-h directory
指定放置生成的本机头文件的位置。
当您指定此选项时,将为包含本机方法或具有使用 java.lang.annotation.Native 注释的一个或多个常量的每个类生成本机头文件。如果该类是包的一部分,则编译器会将本机头文件放入反映包名称的子目录中,并根据需要创建目录。
--help
,–help
或者-?
打印标准选项的概要。
--help-extra
或者-X
打印额外选项的帮助。
-implicit:[none, class]
指定是否为隐式引用的文件生成类文件:
-implicit:class
— 自动生成类文件。
-implicit:none
— 禁止生成类文件。
如果未指定此选项,则默认自动生成类文件。在这种情况下,如果在进行注释处理时生成任何类文件,编译器会发出警告。-implicit
当显式设置该选项时,不会发出警告。请参阅搜索类型。
-Joption
传递option
到运行时系统,其中是java option
命令中描述的 Java 选项之一。例如,设置启动内存为48MB。 -J-Xms48m
笔记:
环境CLASSPATH
变量、-classpath
选项、-bootclasspath
选项和-extdirs
选项不指定用于运行的类javac
。尝试使用这些选项和变量自定义编译器实现是有风险的,并且通常无法实现您想要的效果。如果您必须自定义编译器实现,请使用该-J
选项将选项传递到底层 Java 启动器。
--limit-modules module,module
*
限制可观察模块的范围。
--module module-name
或者-m module-name
仅编译指定的模块并检查时间戳。
--module-path path
或者-p path
指定在哪里找到应用程序模块。
--module-source-path module-source-path
指定在哪里查找多个模块的输入源文件。
--module-version version
指定正在编译的模块的版本。
-nowarn
禁用警告消息。该选项的操作与 选项相同-Xlint:none
。
-parameters
生成用于反映方法参数的元数据。将构造函数和方法的形式参数名称存储在生成的类文件中,以便java.lang.reflect.Executable.getParameters
反射 API 中的方法可以检索它们。
-proc:[none, only]
控制是否完成注释处理和编译。-proc:none
意味着编译发生时没有注释处理。-proc:only
意思是只做了注解处理,不做任何后续的编译。
-processor class1[,class2,class3...]
要运行的注释处理器的名称。这会绕过默认的发现过程。
--processor-module-path path
指定用于查找注释处理器的模块路径。
--processor-path path
或者-processorpath path
指定在哪里可以找到注释处理器。如果未使用此选项,则会在类路径中搜索处理器。
-profile profile
检查所使用的 API 在指定的配置文件中是否可用。
笔记:
这只能在编译 JDK 9 之前的版本时使用。如果适用,请参阅 --release
、-source
、 或中的描述-target
以了解详细信息。
--release release
针对特定 VM 版本的公共、受支持和记录的 API 进行编译。支持的release
目标有6
、7
、8
、9
、10
和11
。
笔记:
当用于--release
支持模块的 Java 平台版本时,您不能使用--add-modules
访问内部 JDK 模块,也不能使用--add-exports
访问模块中的内部 JDK API。
-s directory
指定用于放置生成的源文件的目录。如果类是包的一部分,则编译器会将源文件放入反映包名称的子目录中,并根据需要创建目录。例如:
Oracle Solaris、Linux 和 macOS:如果您指定-s /home/mysrc
并且调用该类com.mypackage.MyClass
,则源文件将放入/home/mysrc/com/mypackage/MyClass.java
.
Windows:如果您指定-s C:\mysrc
并且调用该类com.mypackage.MyClass
,则源文件将放入C:\mysrc\com\mypackage\MyClass.java
.
-source release
指定接受的源代码版本。release
允许 使用以下值:
笔记:
从 JDK 9 开始,javac
不再支持-source
小于或等于5
. 5
如果使用小于或等于的设置,则该javac
命令的行为就像-source 6
已指定一样。
1.6
Java SE 6 中没有引入任何语言更改。但是,源文件中的编码错误现在报告为错误,而不是像早期版本的 Java Platform, Standard Edition 中那样报告为警告。
6
1.6 的同义词。
1.7
编译器接受具有 Java SE 7 中引入的功能的代码。
7
1.7 的同义词。
1.8
编译器接受具有 Java SE 8 中引入的功能的代码。
8
1.8 的同义词。
9
编译器接受具有 Java SE 9 中引入的功能的代码。
10
编译器接受具有 Java SE 10 中引入的功能的代码。
11
默认值。编译器接受具有 Java SE 11 中引入的功能的代码。
--source-path path
或者-sourcepath path
指定在哪里查找输入源文件。这是用于搜索类或接口定义的源代码路径。与用户类路径一样,源路径条目在Oracle Solaris、Linux 和 macOS:
上用冒号 ( )分隔,在 Windows 上用分号 ( ) 分隔。它们可以是目录、JAR 存档或 ZIP 存档。如果使用包,则目录或存档内的本地路径名必须反映包名称。 ;
笔记:
当通过类路径找到的类的源文件也被发现时,可能会重新编译它们。请参阅搜索类型。
--system jdk | none
覆盖系统模块的位置。
-target release
为特定 VM 版本生成类文件。
--upgrade-module—path path
覆盖可升级模块的位置。
-verbose
输出有关编译器正在执行的操作的消息。消息包括有关加载的每个类和编译的每个源文件的信息。
--version
或者-version
打印版本信息。
-Werror
出现警告时终止编译。
javac 的交叉编译选项
默认情况下,对于 JDK 9 之前的版本,类是根据命令附带的平台的引导类进行编译的javac
。而且javac
还支持交叉编译,其中针对不同 Java 平台实现的引导类来编译类。交叉编译时 使用-bootclasspath
和选项很重要。-extdirs
笔记:
这只能在编译 JDK 9 之前的版本时使用。如果适用,请参阅 --release
、-source
、 或中的描述-target
以了解详细信息。
额外选项
--add-exports module/package=other-module(,other-module)
*
other-module
指定当的值为 时,将被视为从其定义模块导出到其他模块或所有未命名模块的包ALL-UNNAMED
。
--add-reads module=other-module(,other-module)
*
指定根据给定模块的需要考虑的附加模块。
--default-module-for-created-files module-name
如果未指定或推断,则指定注释处理器创建的文件的后备目标模块。
-Djava.endorsed.dirs=dirs
覆盖认可的标准路径的位置。
笔记:
这只能在编译 JDK 9 之前的版本时使用。如果适用,请参阅 --release
、-source
、 或中的描述-target
以了解详细信息。
-Djava.ext.dirs=dirs
覆盖已安装扩展的位置。
笔记:
这只能在编译 JDK 9 之前的版本时使用。如果适用,请参阅 --release
、-source
、 或中的描述-target
以了解详细信息。
--doclint-format [html4|html5]
指定文档注释的格式。
--patch-module module=file(:file)
*
使用 JAR 文件或目录中的类和资源覆盖或增强模块。
-Xbootclasspath:path
覆盖引导类文件的位置。
笔记:
这只能在编译 JDK 9 之前的版本时使用。如果适用,请参阅 --release
、-source
、 或中的描述-target
以了解详细信息。
-Xbootclasspath/a:path
向引导类路径添加后缀。
笔记:
这只能在编译 JDK 9 之前的版本时使用。如果适用,请参阅 --release
、-source
、 或中的描述-target
以了解详细信息。
-Xbootclasspath/p:path
向引导类路径添加前缀。
笔记:
这只能在编译 JDK 9 之前的版本时使用。如果适用,请参阅 --release
、-source
、 或中的描述-target
以了解详细信息。
-Xdiags:[compact, verbose]
选择诊断模式。
-Xdoclint
启用对javadoc
评论中问题的建议检查。
-Xdoclint:(all|none|[-]group)[/access]
启用或禁用特定的检查组。
group
可以具有以下值之一:
accessibility
html
missing
reference
syntax
access
指定该选项检查的类和成员的最低可见性级别-Xdoclint
。它可以具有以下值之一(按最可见到最不可见的顺序):
public
protected
package
private
默认access
级别为private
。
有关这些检查组的更多信息,请参阅-Xdoclint
该命令的选项javadoc
。默认情况下,该-Xdoclint
选项在命令中处于禁用状态javac
。
例如,以下选项检查具有受保护和更高访问级别(包括受保护和公共)的类和成员(以及所有检查组):
-Xdoclint:all/protected
以下选项启用所有访问级别的所有组检查,但它不会检查具有 package 及更高访问级别(包括 package、protected 和 public)的类和成员的 HTML 错误:
-Xdoclint:all,-html/package
-Xdoclint/package:[-]packages(,[-]package)
*
启用或禁用特定包中的检查。每个package
都是包的限定名称或包名称前缀后跟句点和星号 ( .*
),它扩展到给定包的所有子包。每个都package
可以使用连字符 ( -
) 作为前缀,以禁用对指定包或多个包的检查。
-Xlint
启用所有建议的警告。在此版本中,建议启用所有可用警告。
-Xlint:[-]key(,[-]key)
*
提供启用或禁用的警告,以逗号 ( ,
) 分隔。在键前面添加连字符 ( -
) 可禁用指定的警告。
支持的值为key
:
all
:启用所有警告。
auxiliaryclass
:警告隐藏在源文件中并从其他文件中使用的辅助类。
cast
:警告使用不必要的强制转换。
classfile
:警告与类文件内容相关的问题。
deprecation
:警告有关使用已弃用的项目。
dep-ann
:对标记为已弃用javadoc
但没有@Deprecated
注释的项目发出警告。
divzero
:警告除以常数整数 0。
empty
:警告 后出现空语句if
。
exports
:警告有关模块导出的问题。
fallthrough
:警告从 switch 语句的一种情况跳到下一种情况。
finally
:警告finally
不正常终止的子句。
module
:警告模块系统相关问题。
opens
:警告与模块打开相关的问题。
options
:警告与使用命令行选项相关的问题。
overloads
:警告与方法重载相关的问题。
overrides
:警告与方法覆盖相关的问题。
path
:警告命令行上的无效路径元素。
processing
:警告与注释处理相关的问题。
rawtypes
:警告有关使用原始类型的信息。
removal
:警告有关使用已标记为删除的 API 的情况。
requires-automatic
:警告开发人员在 require 子句中使用自动模块。
requires-transitive-automatic
:警告需要传递的自动模块。
serial
:警告不提供序列版本 ID 的可序列化类。还警告从可序列化元素访问非公共成员。
static
:关于使用实例访问静态成员的警告。
try
:警告与使用 try 块(即 try-with-resources)相关的问题。
unchecked
:对未经检查的操作发出警告。
varargs
:警告潜在不安全的vararg
方法。
none
:禁用所有警告。
请参阅使用 -Xlint 键的示例。
-Xmaxerrs number
设置要打印的最大错误数。
-Xmaxwarns number
设置要打印的最大警告数。
-Xpkginfo:[always, legacy, nonempty]
使用以下选项之一 指定命令何时以及如何从文件javac
生成文件:package-info.class
package-info.java
always
package-info.class
为每个文件生成一个文件package-info.java
。如果您使用 Ant 等构建系统,该选项可能会很有用,它会检查每个.java
文件是否都有对应的.class
文件。
legacy
package-info.class
仅当包含注释时才生成文件package-info.java
。package-info.class
如果仅包含注释,此选项不会生成文件package-info.java
。
笔记:
package-info.class
如果文件中的所有注释都package-info.java
具有RetentionPolicy.SOURCE
.
nonempty
package-info.class
仅当包含带 或 的package-info.java
注释时才生成文件。 RetentionPolicy.CLASS
RetentionPolicy.RUNTIME
-Xplugin:name args
指定要运行的插件的名称和可选参数。
-Xprefer:[source
,newer]
指定使用以下选项之一找到隐式编译类的源文件和类文件时要读取的文件。请参阅搜索类型。
-Xprefer:newer
:读取某个类型的较新的源文件或类文件(默认)。
-Xprefer:source
:读取源文件。-Xprefer:source
当您想要确保任何注释处理器都可以访问使用保留策略声明的注释时使用SOURCE
。
-Xprint
出于调试目的打印指定类型的文本表示。这不执行注释处理或编译。输出的格式可能会改变。
-XprintProcessorInfo
打印有关要求处理器处理哪些注释的信息。
-XprintRounds
打印有关初始和后续注释处理轮次的信息。
-Xstdout filename
将编译器消息发送到指定文件。默认情况下,编译器消息转到System.err
.
javac 命令行参数文件
参数文件可以包含javac
任意组合的选项和源文件名。文件中的参数可以用空格或换行符分隔。如果文件名包含嵌入空格,则将整个文件名放在双引号中。
参数文件中的文件名是相对于当前目录的,而不是相对于参数文件的位置的。*
这些列表中不允许使用通配符 ( )(例如用于指定*.java
)。不支持使用 at 符号 ( @
) 递归解释文件。这些-J
选项不受支持,因为它们被传递到启动器,而启动器不支持参数文件。
执行javac
命令时,传入每个参数文件的路径和名称,并以 at 符号 ( @
) 开头。当该javac
命令遇到以 at 符号 ( ) 开头的参数时@
,它会将该文件的内容展开到参数列表中。
使用 javac @filename 的示例
单个参数文件
您可以使用名为的单个参数文件argfile
来保存所有javac
参数:
javac @argfile
此参数文件可以包含以下两个参数文件示例中显示的两个文件的内容。
两个参数文件
您可以创建两个参数文件:一个用于选项javac
,另一个用于源文件名。请注意,以下列表没有续行符。
options
创建一个包含以下内容 的文件:
Oracle Solaris、Linux 和 macOS:
-d classes
-g
-sourcepath /java/pubs/ws/1.3/src/share/classes
Windows:
-d classes
-g
-sourcepath C:\java\pubs\ws\1.3\src\share\classes
classes
创建一个包含以下内容 的文件:
MyClass1.java
MyClass2.java
MyClass3.java
然后,运行javac
命令如下:
javac @options @classes
带有路径的参数文件
参数文件可以有路径,但文件内的任何文件名都是相对于当前工作目录的(不是path1
或path2
):
javac @path1/options @path2/classes
使用 -Xlint 键的示例
cast
警告不必要和多余的强制转换,例如:
String s = (String) "Hello!"
classfile
警告与类文件内容相关的问题。
deprecation
关于使用已弃用的项目的警告。例如:
java.util.Date myDate = new java.util.Date();
int currentDay = myDate.getDay();
该方法java.util.Date.getDay
自 JDK 1.1 起已被弃用。
dep-ann
对使用@deprecated
Javadoc 注释记录但没有@Deprecated
注释的项目发出警告,例如:
/**
* @deprecated As of Java SE 7, replaced by {@link #newMethod()}
*/
public static void deprecatedMethod() { }
public static void newMethod() { }
divzero
警告除以常量整数 0 的情况,例如:
int divideByZero = 42 / 0;
empty
警告语句后的空语句if
,例如:
class E {
void m() {
if (true) ;
}
}
fallthrough
检查开关块是否有掉落情况,并为发现的任何情况提供警告消息。失败案例是 switch 块中的案例,除了块中的最后一个案例,其代码不包含 break 语句,允许代码执行从该案例跌落到下一个案例。例如,此 switch 块中 case 1 标签后面的代码不以 break 语句结尾:
switch (x) {
case 1:
System.out.println("1");
// No break statement here.
case 2:
System.out.println("2");
}
如果-Xlint:fallthrough
在编译此代码时使用了该选项,则编译器会发出有关可能陷入 case 的警告,并附带相关 case 的行号。
finally
对finally
无法正常完成的子句发出警告,例如:
public static int m() {
try {
throw new NullPointerException();
} catch (NullPointerException(); {
System.err.println("Caught NullPointerException.");
return 1;
} finally {
return 0;
}
}
编译器为本示例中的块生成警告finally
。调用该方法时int
,它返回值 0。finally
当块退出时,块就会执行try
。在此示例中,当控制权转移到catch
块时,该int
方法退出。但是,该finally
块必须执行,因此即使控制权转移到方法外部,它也会被执行。
options
警告与使用命令行选项相关的问题。请参阅javac 的交叉编译选项。
overrides
警告与方法覆盖相关的问题。例如,考虑以下两个类:
public class ClassWithVarargsMethod {
void varargsMethod(String... s) { }
}
public class ClassWithOverridingMethod extends ClassWithVarargsMethod {
@Override
void varargsMethod(String[] s) { }
}
编译器会生成类似于以下内容的警告:
warning: [override] varargsMethod(String[]) in ClassWithOverridingMethod
overrides varargsMethod(String...) in ClassWithVarargsMethod; overriding
method is missing '...'
当编译器遇到一个varargs
方法时,它会将varargs
形式参数转换为数组。在方法中ClassWithVarargsMethod.varargsMethod
,编译器将varargs
形式参数转换String... s
为形式参数String[] s
,即与方法的形式参数相匹配的数组ClassWithOverridingMethod.varargsMethod
。因此,该示例可以编译。
path
警告命令行上的无效路径元素和不存在的路径目录(关于类路径、源路径和其他路径)。此类警告无法通过@SuppressWarnings
注释来抑制。例如:
Oracle Solaris、Linux 和 macOS: javac -Xlint:path -classpath /nonexistentpath Example.java
Windows: javac -Xlint:path -classpath C:\nonexistentpath Example.java
processing
警告与注释处理相关的问题。当您的类带有注释,并且您使用的注释处理器无法处理该类型的异常时,编译器会生成此警告。例如,以下是一个简单的注释处理器:
源文件AnnocProc.java:
import java.util.*;
import javax.annotation.processing.*;
import javax.lang.model.*;
import javaz.lang.model.element.*;
@SupportedAnnotationTypes("NotAnno")
public class AnnoProc extends AbstractProcessor {
public boolean process(Set extends TypeElement> elems, RoundEnvironment renv){
return true;
}
public SourceVersion getSupportedSourceVersion() {
return SourceVersion.latest();
}
}
源文件 AnnosWithoutProcessors.java:
@interface Anno { }
@Anno
class AnnosWithoutProcessors { }
以下命令编译注释处理器AnnoProc
,然后针对源文件运行此注释处理器AnnosWithoutProcessors.java
:
javac AnnoProc.java
javac -cp . -Xlint:processing -processor AnnoProc -proc:only AnnosWithoutProcessors.java
当编译器针对源文件运行注释处理器时AnnosWithoutProcessors.java
,它会生成以下警告:
warning: [processing] No processor claimed any of these annotations: Anno
要解决此问题,您可以将类中定义和使用的注释AnnosWithoutProcessors
从重命名Anno
为NotAnno
。
rawtypes
警告对原始类型进行未经检查的操作。以下语句会生成rawtypes
警告:
void countElements(List l) { ... }
以下示例不会生成rawtypes
警告:
void countElements(List> l) { ... }
List
是原始类型。但是,List>
是无界通配符参数化类型。因为List
是参数化接口,所以始终指定其类型参数。在此示例中,List
形式参数使用无界通配符 ( ?
) 作为其形式类型参数来指定,这意味着该countElements
方法可以接受List
接口的任何实例化。
serial
警告可serialVersionUID
序列化类上缺少定义。例如:
public class PersistentTime implements Serializable
{
private Date time;
public PersistentTime() {
time = Calendar.getInstance().getTime();
}
public Date getTime() {
return time;
}
}
编译器生成以下警告:
warning: [serial] serializable class PersistentTime has no definition of
serialVersionUID
如果可序列化类未显式声明名为 的字段serialVersionUID
,则序列化运行时环境会serialVersionUID
根据该类的各个方面计算该类的默认值,如 Java 对象序列化规范中所述。但是,强烈建议所有可序列化类显式声明serialVersionUID
值,因为计算serialVersionUID
值的默认过程对类详细信息高度敏感,而类详细信息可能因编译器实现而异。因此,这可能会InvalidClassExceptions
在反序列化期间导致意外情况。为了保证serialVersionUID
不同 Java 编译器实现之间的值一致,可序列化类必须声明显式serialVersionUID
值。
static
警告与使用静态变量相关的问题,例如:
class XLintStatic {
static void m1() { }
void m2() { this.m1(); }
}
编译器生成以下警告:
warning: [static] static method should be qualified by type name,
XLintStatic, instead of by an expression
为了解决这个问题,您可以调用如下 static
方法:m1
XLintStatic.m1();
或者,您可以static
从方法的声明中删除关键字m1
。
try
警告与块使用相关的问题try
,包括 try-with-resources 语句。例如,由于未使用块 ac
中声明的资源,因此会为以下语句生成警告:try
try ( AutoCloseable ac = getResource() ) { // do nothing}
unchecked
提供 Java 语言规范强制要求的未经检查的转换警告的更多详细信息,例如:
List l = new ArrayList();
List ls = l; // unchecked warning
在类型擦除期间,类型ArrayList
和分别List
变为ArrayList
和List
。
该ls
命令具有参数化类型List
。当List
引用 byl
分配给时ls
,编译器会生成未经检查的警告。在编译时,编译器和JVM无法确定是否l
引用了某种List
类型。在本例中,l
不引用类型List
。结果,出现了堆污染。
当静态类型为 的List
对象被分配给另一个具有不同静态类型 的对象时,就会发生堆污染情况。然而,编译器仍然允许这种分配。它必须允许此分配以保持与不支持泛型的 Java SE 版本的向后兼容性。由于类型擦除,两者都变为. 因此,编译器允许将原始类型为,的对象分配给对象。 l
List
List
ls
List
List
List
List
l
,
List
ls
varargs
警告不安全地使用可变参数 ( varargs
) 方法,特别是那些包含不可具体化参数的方法,例如:
public class ArrayBuilder {
public static void addToList (List listArg, T... elements) {
for (T x : elements) {
listArg.add(x);
}
}
}
不可具体化类型是其类型信息在运行时不完全可用的类型。
编译器会针对该方法的定义生成以下警告ArrayBuilder.addToList
:
warning: [varargs] Possible heap pollution from parameterized vararg type T
当编译器遇到 varargs 方法时,它将varargs
形式参数转换为数组。但是,Java 编程语言不允许创建参数化类型的数组。在方法中ArrayBuilder.addToList
,编译器将varargs
形式参数T...
元素转换为形式参数T[]
元素,即数组。但是,由于类型擦除,编译器将varargs
形式参数转换为Object[]
元素。因此,存在堆污染的可能性。
通过提供命令行参数进行编译的示例
要像提供命令行参数一样进行编译,请使用以下语法:
JavaCompiler javac = ToolProvider.getSystemJavaCompiler();
该示例将诊断信息写入标准输出流,并返回javac
从命令行调用时命令给出的退出代码。
您可以使用javax.tools.JavaCompiler
界面中的其他方法来处理诊断、控制文件的读取和写入位置等。
旧界面
笔记:
保留此 API 只是为了向后兼容。所有新代码都应使用 Java 编译器 API。
该类com.sun.tools.javac.Main
提供了两个静态方法来从程序中调用编译器:
public static int compile(String[] args);
public static int compile(String[] args, PrintWriter out);
该args
参数表示通常传递给编译器的任何命令行参数。
该out
参数指示编译器诊断输出的定向位置。
该return
值相当于exit
来自 的值javac
。
笔记:
在名称以 开头的包com.sun.tools.javac
( 的子包com.sun.tools.javac
)中找到的所有其他类和方法都是严格内部的,并且可能随时更改。
编译多个源文件的示例
此示例编译包中的Aloha.java
、GutenTag.java
、Hello.java
和Hi.java
源文件greetings
。
Oracle Solaris、Linux 和 macOS:
% javac greetings/*.java
% ls greetings
Aloha.class GutenTag.class Hello.class Hi.class
Aloha.java GutenTag.java Hello.java Hi.java
Windows:
C:\>javac greetings\*.java
C:\>dir greetings
Aloha.class GutenTag.class Hello.class Hi.class
Aloha.java GutenTag.java Hello.java Hi.java
指定用户类路径的示例
更改上一示例中的一个源文件后,重新编译它:
Oracle Solaris、Linux 和 macOS:
pwd
/examples
javac greetings/Hi.java
Windows:
C:\>cd
\examples
C:\>javac greetings\Hi.java
因为greetings.Hi
引用了greetings
包中的其他类,所以编译器需要找到这些其他类。前面的示例之所以有效,是因为默认用户类路径是包含包目录的目录。如果您想重新编译此文件而不关心您所在的目录,则可以examples
通过设置 将该目录添加到用户类路径中CLASSPATH
。本示例使用该-classpath
选项。
Oracle Solaris、Linux 和 macOS:
javac -classpath /examples /examples/greetings/Hi.java
Windows:
C:\>javac -classpath \examples \examples\greetings\Hi.java
如果您更改greetings.Hi
为使用横幅实用程序,则还需要可以通过用户类路径访问该实用程序。
Oracle Solaris、Linux 和 macOS:
javac -classpath /examples:/lib/Banners.jar \
/examples/greetings/Hi.java
Windows:
C:\>javac -classpath \examples;\lib\Banners.jar ^
\examples\greetings\Hi.java
要执行包中的类greetings
,程序需要访问greetings
包以及这些greetings
类使用的类。
Oracle Solaris、Linux 和 macOS:
java -classpath /examples:/lib/Banners.jar greetings.Hi
Windows:
C:\>java -classpath \examples;\lib\Banners.jar greetings.Hi
该javac
命令为注释处理提供直接支持,取代了单独的注释处理命令 的需要apt
。
javax.annotation.processing
注释处理器的 API 在和包和子包中定义javax.lang.model
。
注释处理的工作原理
除非使用该选项禁用注释处理-proc:none
,否则编译器将搜索任何可用的注释处理器。可以使用选项指定搜索路径-processorpath
。如果未指定路径,则使用用户类路径。处理器通过名为 的服务提供商配置文件来定位META-INF/services/javax.annotation.processing
。搜索路径上的处理器。此类文件应包含要使用的任何注释处理器的名称,每行列出一个。或者,可以使用 选项显式指定处理器-processor
。
在命令行上扫描源文件和类以确定存在哪些注释后,编译器会查询处理器以确定它们处理哪些注释。当找到匹配时,将调用处理器。处理器可以声明它处理的注释,在这种情况下,不会进一步尝试为这些注释查找任何处理器。声明所有注释后,编译器不会搜索其他处理器。
如果任何处理器生成新的源文件,则会进行另一轮注释处理:扫描任何新生成的源文件,并像以前一样处理注释。前几轮调用的任何处理器也会在所有后续轮次中调用。这一直持续到没有新的源文件生成为止。
在没有生成新源文件的一轮发生后,最后一次调用注释处理器,以使它们有机会完成任何剩余的工作。最后,除非-proc:only
使用该选项,否则编译器将编译原始源文件和所有生成的源文件。
为了编译源文件,编译器通常需要有关类型的信息,但类型定义并不在命令行指定的源文件中。
编译器需要源文件中使用、扩展或实现的每个类或接口的类型信息。这包括源文件中未明确提及但通过继承提供信息的类和接口。
例如,当您创建 的子类时,您也在使用: 、和 的java.awt.Window
祖先类。 Window
java.awt.Container
java.awt.Component
java.lang.Object
当编译器需要类型信息时,它会搜索定义该类型的源文件或类文件。编译器首先在引导类和扩展类中搜索类文件,然后在用户类路径(默认情况下为当前目录)中搜索类文件。用户类路径是通过设置CLASSPATH
环境变量或使用-classpath
选项来定义的。
如果设置该-sourcepath
选项,编译器将在指定路径中搜索源文件。否则,编译器将在用户类路径中搜索类文件和源文件。
您可以使用-bootclasspath
和-extdirs
选项指定不同的引导程序或扩展类。
请参阅javac 的交叉编译选项。
成功的类型搜索可能会生成类文件、源文件或两者。如果两者都找到,那么您可以使用该-Xprefer
选项来指示编译器使用哪一个。如果newer
指定,则编译器使用两个文件中较新的一个。如果source
指定,编译器将使用源文件。默认为newer
.
如果类型搜索找到所需类型的源文件(无论是其本身还是作为选项设置的结果)-Xprefer
,则编译器将读取该源文件以获取其所需的信息。默认情况下,编译器还会编译源文件。您可以使用该-implicit
选项来指定行为。如果none
指定,则不会为源文件生成任何类文件。如果class
指定,则为源文件生成类文件。
在注释处理完成之前,编译器可能不会发现需要某些类型信息。当在源文件中找到类型信息并且未-implicit
指定选项时,编译器会发出警告,表明正在编译该文件而无需进行注释处理。要禁用警告,请在命令行上指定文件(以便它将受到注释处理)或使用选项-implicit
指定是否应为此类源文件生成类文件。