Writer或 OutputStream上调用close方法后,如此创建的源文件和类文件将由工具在随后的一轮处理中考虑处理。区分三种文件:源文件、类文件和辅助资源文件。
有两个不同的受支持位置(逻辑文件系统中的子树)用于放置新创建的文件:一个用于 新的源文件 ,一个用于 新类文件 。 (这些可能在工具的命令行上指定,例如,使用 -s 和 -d 等标志。)新源文件和新类文件的实际位置在工具的特定运行中可能不同也可能不同。可以在任一位置创建资源文件。读取和写入资源的方法采用相对名称参数。相对名称是由 '/' 分隔的非空、非空路径段序列; '.' 和 '..' 是无效路径段。有效的相对名称必须匹配 RFC 3986 的“无根路径”规则,第 3.3 节。
文件创建方法采用可变数量的参数,以允许将 originating elements 作为提示提供给工具基础结构,以更好地管理依赖关系。原始元素是导致注解处理器尝试创建新文件的类或接口或包(代表 package-info 文件)或模块(代表 module-info 文件)。换句话说,原始元素旨在具有 compilation units 的粒度(JLS 部分 7.3 ),本质上是文件级粒度,而不是更精细的粒度,例如方法或字段声明。
例如,如果注解处理器尝试创建源文件 GeneratedFromUserSource 以响应处理
@Generate
public class UserSource {}
UserSource 的类型元素应作为创建方法调用的一部分传递,如下所示:
filer.createSourceFile("GeneratedFromUserSource",
eltUtils.getTypeElement("UserSource"));
如果没有原始元素,则不需要传递任何元素。此信息可用于增量环境以确定是否需要重新运行处理器或删除生成的文件。非增量环境可能会忽略原始元素信息。
在注释处理工具的每次运行期间,具有给定路径名的文件可能只被创建一次。如果该文件在第一次尝试创建之前已经存在,则旧内容将被删除。任何在运行期间创建相同文件的后续尝试都将抛出 FilerException ,尝试为相同类型名称或相同包名称创建类文件和源文件也是如此。工具的初始输入被认为是由第零轮创建的;因此,尝试创建与这些输入之一相对应的源文件或类文件将导致 FilerException 。
通常,处理器不得有意尝试覆盖不是由某些处理器生成的现有文件。 Filer 可能会拒绝打开对应于现有类或接口的文件的尝试,例如 java.lang.Object 。同样,注释处理工具的调用者不得故意配置该工具,使得发现的处理器将尝试覆盖未生成的现有文件。
如果环境配置为可访问该类或接口,处理器可以通过包含 Generated 注释来指示生成源文件或类文件。
- API 注意:
- 重写文件的某些效果可以通过使用装潢师风格的图案。不是直接修改类,而是设计类,以便通过注释处理生成其超类,或者通过注释处理生成类的子类。如果生成了子类,则父类可以设计为使用工厂而不是公共构造方法,以便只有子类实例可以呈现给父类的客户。
- 自从:
- 1.6
-
方法总结
修饰符和类型方法描述createClassFile(CharSequence name, Element... originatingElements) 创建一个新的类文件,并返回一个对象以允许写入它。createResource(JavaFileManager.Location location, CharSequence moduleAndPkg, CharSequence relativeName, Element... originatingElements) 创建一个新的用于写入的辅助资源文件并为其返回一个文件对象。createSourceFile(CharSequence name, Element... originatingElements) 创建一个新的源文件并返回一个对象以允许写入它。getResource(JavaFileManager.Location location, CharSequence moduleAndPkg, CharSequence relativeName) 返回用于读取现有资源的对象。
-
方法详情
-
createSourceFile
JavaFileObject createSourceFile(CharSequence name, Element ... originatingElements) throws IOException 创建一个新的源文件并返回一个对象以允许写入它。可以创建类、接口或包的源文件。文件的名称和路径(相对于 源文件的根输出位置 )基于要在该文件中声明的项目的名称以及项目的指定模块(如果有)。如果在单个文件(即单个编译单元)中声明了多个类或接口,则文件的名称应对应于主要顶级类或接口的名称(例如公共类或接口) ).还可以创建源文件来保存有关包的信息,包括包注释。要为命名包创建源文件,请将
name参数作为包的名称后跟".package-info";要为未命名的包创建源文件,请使用"package-info"。可选模块名称以类型名称或包名称为前缀,并使用“
/”字符分隔。例如,要为模块foo中的类a.B创建源文件,请使用"foo/a.B"的name参数。如果没有给出明确的模块前缀并且环境支持模块,则会推断出合适的模块。如果无法推断出合适的模块,则会抛出
FilerException。一个实现可以使用关于注释处理工具配置的信息作为推理的一部分。not 支持在 named 模块中为 unnamed 包创建源文件。
- API 注意:
-
要使用特定的 charset 对文件内容进行编码,可以从返回对象的
OutputStream创建具有所选字符集的OutputStreamWriter。如果返回对象中的Writer直接用于写入,则其字符集由实现决定。注释处理工具可能有一个-encoding标志或类似的选项来指定它;否则,它通常是平台的默认编码。为避免后续错误,源文件的内容应与用于此运行的 源版本 兼容。
- 实现注意事项:
-
在参考实现中,如果注解处理工具是处理单个模块M, 然后M用作没有显式模块前缀创建的文件的模块。如果该工具正在处理多个模块,并且
Elements.getPackageElement(package-of(name))返回一个包,则拥有返回包的模块将用作目标模块。如果无法使用上述规则确定目标模块,则可以使用单独的选项来提供目标模块。 - 参数:
name- 在此文件中声明的主体类或接口的规范(完全限定)名称或包名称后跟".package-info"用于包信息文件originatingElements- 与此文件的创建有因果关系的类、接口、包或模块元素可能被省略或null- 返回:
-
a
JavaFileObject写入新的源文件 - 抛出:
FilerException- 如果已经创建了相同的路径名,已经创建了相同的类或接口,否则该名称对于请求创建的实体无效,如果无法确定目标模块,如果目标模块不可写,或者当环境不支持模块时指定模块。IOException- 如果无法创建文件- 看Java 语言规范:
-
7.3 编译单元
-
createClassFile
JavaFileObject createClassFile(CharSequence name, Element ... originatingElements) throws IOException 创建一个新的类文件,并返回一个对象以允许写入它。可以为类、接口或包创建类文件。文件的名称和路径(相对于 类文件的根输出位置 )基于要声明的项目的名称以及项目的指定模块(如果有)。还可以创建一个类文件来保存有关包的信息,包括包注释。要为命名包创建类文件,请将
name参数作为包的名称,后跟".package-info";不支持为未命名的包创建类文件。可选模块名称以类型名称或包名称为前缀,并使用“
/”字符分隔。例如,要在模块foo中为类a.B创建类文件,请使用"foo/a.B"的name参数。如果没有给出明确的模块前缀并且环境支持模块,则会推断出合适的模块。如果无法推断出合适的模块,则会抛出
FilerException。一个实现可以使用关于注释处理工具配置的信息作为推理的一部分。not 支持在 named 模块中为 unnamed 包创建类文件。
- API 注意:
- 为避免后续错误,类文件的内容应与用于此运行的 源版本 兼容。
- 实现注意事项:
-
在参考实现中,如果注解处理工具是处理单个模块M, 然后M用作没有显式模块前缀创建的文件的模块。如果该工具正在处理多个模块,并且
Elements.getPackageElement(package-of(name))返回一个包,则拥有返回包的模块将用作目标模块。如果无法使用上述规则确定目标模块,则可以使用单独的选项来提供目标模块。 - 参数:
name- 正在写入的类或接口的二进制名称或包名称后跟".package-info"用于包信息文件originatingElements- 与此文件的创建有因果关系的类或接口或包或模块元素,可能被省略或null- 返回:
-
a
JavaFileObject写入新的类文件 - 抛出:
FilerException- 如果已经创建了相同的路径名,已经创建了相同的类或接口,该名称对于类或接口无效,如果无法确定目标模块,如果目标模块不可写,或者当环境不支持模块时指定模块。IOException- 如果无法创建文件
-
createResource
FileObject createResource(JavaFileManager.Location location, CharSequence moduleAndPkg, CharSequence relativeName, Element ... originatingElements) throws IOException 创建一个新的用于写入的辅助资源文件并为其返回一个文件对象。该文件可能与新创建的源文件、新创建的二进制文件或其他受支持的位置一起位于。必须支持位置CLASS_OUTPUT和SOURCE_OUTPUT。资源可以相对于某些模块和/或包(如源文件和类文件)命名,并从那里通过相对路径名命名。从广义上讲,新文件的完整路径名将是location、moduleAndPkg和relativeName的串联。如果moduleAndPkg包含“/”字符,则“/”字符之前的前缀是模块名称,“/”字符之后的后缀是包名称。包后缀可以为空。如果moduleAndPkg不包含“/”字符,则整个参数被解释为包名称。如果给定的位置既不是 面向模块的位置 也不是 包含多个模块的输出位置 ,并且给出了显式模块前缀,则抛出
FilerException。如果给定的位置是面向模块的位置,或者是包含多个模块的输出位置,并且没有给出明确的模块前缀,则会推断出合适的模块。如果无法推断出合适的模块,则会抛出
FilerException。一个实现可以使用关于注释处理工具配置的信息作为推理的一部分。通过此方法创建的文件not 已注册用于注释处理,即使文件的完整路径名对应于新源文件或新类文件的完整路径名也是如此。
- 实现注意事项:
-
在参考实现中,如果注解处理工具是处理单个模块M, 然后M用作没有显式模块前缀创建的文件的模块。如果该工具正在处理多个模块,并且
Elements.getPackageElement(package-of(name))返回一个包,则拥有返回包的模块将用作目标模块。如果无法使用上述规则确定目标模块,则可以使用单独的选项来提供目标模块。 - 参数:
location- 新文件的位置moduleAndPkg- 文件应命名的相关模块和/或包,如果没有则为空字符串relativeName- 文件的最终路径名组件originatingElements- 与此文件的创建有因果关系的类或接口或包或模块元素,可能被省略或null- 返回:
FileObject写入新资源- 抛出:
IOException- 如果无法创建文件FilerException- 如果已经创建了相同的路径名,如果无法确定目标模块,或者目标模块不可写,或者指定了显式目标模块但位置不支持它。IllegalArgumentException- 对于不受支持的位置IllegalArgumentException- 如果moduleAndPkg格式错误IllegalArgumentException- 如果relativeName不是相对的
-
getResource
FileObject getResource(JavaFileManager.Location location, CharSequence moduleAndPkg, CharSequence relativeName) throws IOException 返回用于读取现有资源的对象。必须支持位置CLASS_OUTPUT和SOURCE_OUTPUT。如果
moduleAndPkg包含“/”字符,则“/”字符之前的前缀是模块名称,“/”字符之后的后缀是包名称。包后缀可以为空;但是,如果存在模块名称,则它必须是非空的。如果moduleAndPkg不包含“/”字符,则整个参数被解释为包名称。如果给定的位置既不是 面向模块的位置 也不是 包含多个模块的输出位置 ,并且给出了显式模块前缀,则抛出
FilerException。如果给定的位置是面向模块的位置,或者是包含多个模块的输出位置,并且没有给出明确的模块前缀,则会推断出合适的模块。如果无法推断出合适的模块,则会抛出
FilerException。一个实现可以使用关于注释处理工具配置的信息作为推理的一部分。- 实现注意事项:
-
在参考实现中,如果注解处理工具是处理单个模块M, 然后M用作没有显式模块前缀的文件读取模块。如果该工具正在处理多个模块,并且
Elements.getPackageElement(package-of(name))返回一个包,则拥有返回包的模块将用作源模块。如果无法使用上述规则确定目标模块,则可以使用单独的选项来提供目标模块。 - 参数:
location- 文件的位置moduleAndPkg- 应该搜索文件的模块和/或包,如果没有则为空字符串relativeName- 文件的最终路径名组件- 返回:
- 读取文件的对象
- 抛出:
FilerException- 如果已经打开相同的路径名进行写入,如果无法确定源模块,或者目标模块不可写,或者指定了显式目标模块但位置不支持它。IOException- 如果文件无法打开IllegalArgumentException- 对于不受支持的位置IllegalArgumentException- 如果moduleAndPkg格式错误IllegalArgumentException- 如果relativeName不是相对的
-