java文档收集之javac

  官网地址:javac

欢迎关注留言,我是收集整理小能手,工具翻译,仅供参考,笔芯笔芯.

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 命令行参数文件。 @filenamejavacjavac

源代码文件名必须有.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 选项概述

编译器具有当前开发环境支持的一组标准选项和交叉编译选项。编译器还有一组非标准选项,这些选项特定于当前虚拟机和编译器实现,但将来可能会发生变化。非标准选项以 开头-Xjavac以下部分描述了 不同的选项集:

  • 标准选项

  • 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目标有67891011

笔记:

当用于--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小于或等于55如果使用小于或等于的设置,则该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.classpackage-info.java

always

package-info.class为每个文件生成一个文件package-info.java。如果您使用 Ant 等构建系统,该选项可能会很有用,它会检查每个.java文件是否都有对应的.class文件。

legacy

package-info.class仅当包含注释时才生成文件package-info.javapackage-info.class如果仅包含注释,此选项不会生成文件package-info.java

笔记:

package-info.class如果文件中的所有注释都package-info.java具有RetentionPolicy.SOURCE.

nonempty

package-info.class仅当包含带 或 的package-info.java注释时才生成文件。 RetentionPolicy.CLASSRetentionPolicy.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

带有路径的参数文件

参数文件可以有路径,但文件内的任何文件名都是相对于当前工作目录的(不是path1path2):

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

对使用@deprecatedJavadoc 注释记录但没有@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 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从重命名AnnoNotAnno

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变为ArrayListList

ls命令具有参数化类型List。当List引用 byl分配给时ls,编译器会生成未经检查的警告。在编译时,编译器和JVM无法确定是否l引用了某种List类型。在本例中,l不引用类型List。结果,出现了堆污染。

当静态类型为 的List对象被分配给另一个具有不同静态类型 的对象时,就会发生堆污染情况。然而,编译器仍然允许这种分配。它必须允许此分配以保持与不支持泛型的 Java SE 版本的向后兼容性。由于类型擦除,两者都变为. 因此,编译器允许将原始类型为,的对象分配给对象。 lListListlsListListListListl,Listls

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.javaGutenTag.javaHello.javaHi.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祖先类。 Windowjava.awt.Containerjava.awt.Componentjava.lang.Object

当编译器需要类型信息时,它会搜索定义该类型的源文件或类文件。编译器首先在引导类和扩展类中搜索类文件,然后在用户类路径(默认情况下为当前目录)中搜索类文件。用户类路径是通过设置CLASSPATH环境变量或使用-classpath选项来定义的。

如果设置该-sourcepath选项,编译器将在指定路径中搜索源文件。否则,编译器将在用户类路径中搜索类文件和源文件。

您可以使用-bootclasspath-extdirs选项指定不同的引导程序或扩展类。

请参阅javac 的交叉编译选项。

成功的类型搜索可能会生成类文件、源文件或两者。如果两者都找到,那么您可以使用该-Xprefer选项来指示编译器使用哪一个。如果newer指定,则编译器使用两个文件中较新的一个。如果source指定,编译器将使用源文件。默认为newer.

如果类型搜索找到所需类型的源文件(无论是其本身还是作为选项设置的结果)-Xprefer,则编译器将读取该源文件以获取其所需的信息。默认情况下,编译器还会编译源文件。您可以使用该-implicit选项来指定行为。如果none指定,则不会为源文件生成任何类文件。如果class指定,则为源文件生成类文件。

在注释处理完成之前,编译器可能不会发现需要某些类型信息。当在源文件中找到类型信息并且未-implicit指定选项时,编译器会发出警告,表明正在编译该文件而无需进行注释处理。要禁用警告,请在命令行上指定文件(以便它将受到注释处理)或使用选项-implicit指定是否应为此类源文件生成类文件。

你可能感兴趣的:(java,开发语言)