java api model_Java编译器API简介

news/2024/10/18 0:32:35/

今天给大家分享的是Java编译器API简介,文章部分内容摘自【优锐课】学习笔记。

Java编译器API

Java编译器API是Java模块(称为java.compiler)的一部分。该模块包括语言模型和注释处理,以及编译器API。它定义了Java编程语言和编译器工具的类型和模型声明,可以在执行期间从应用程序代码中调用它们。注释处理有助于访问注释处理器,可以将其视为Java编译器的插件。它使注释处理器和注释处理工具环境之间能够通信。模型,元素和类型包处理Java编程语言的元素,而util包则帮助处理程序元素和类型。

编译工具

javax.tools包提供了与Java编译器一起使用的接口和类,并且可以在执行期间从程序中调用它。 它提供了一个框架,该框架允许客户端从其自己的应用程序代码定位和运行编译器。它还提供了服务提供者接口(SPI),用于对诊断的结构化访问和用于覆盖文件访问的文件抽象。ToolProvider类提供了编译器API的入口点。此类提供了一些方法来定位编译器的工具提供者。 例如,我们可以轻松地找到系统中安装的编译器支持的Java源版本列表。

1 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();

2 for(SourceVersion sv:compiler.getSourceVersions()){

3 System.out.println(sv);

4 }

输出如下(根据系统中安装的版本)。

48304ba5e6f9fe08f3fa1abda7d326ab.png

1 RELEASE_3

2 RELEASE_4

3 RELEASE_5

4 RELEASE_6

5 RELEASE_7

6 RELEASE_8

7 RELEASE_9

8 RELEASE_10

9 RELEASE_11

48304ba5e6f9fe08f3fa1abda7d326ab.png

在这种情况下,ToolProvider会找到默认的编译器。通过使用服务提供者机制,还可以找到替代的编译器或工具。如果某些供应商提供Java编译器,则jar文件将包含文件META-INF / service / javax.tool.JavaCompiler,并且将包含一行:com.vendor.VendorJavaCompiler。我们可以将jar文件放入类路径中,并按以下方式定位它:

1 JavaCompiler vendorJavaCompiler =

2 ServiceLoader.load(JavaCompiler.class).iterator().next();

ServiceProvider是Java的util类之一,用于查找和加载部署在执行环境中的服务提供者。

找到JavaCompiler后,就可以通过Java源代码执行各种编译诊断任务。为了说明这个想法,让我们首先创建一个简单的类,如下所示:

48304ba5e6f9fe08f3fa1abda7d326ab.png

1 package com.mano.jcapidemo;

2 import java.util.Random;

3 public class MyClass {

4 public static void main(String[] args){

5 Random r = new Random();

6 System.out.println("Today your Lucky Number is:

7 "+r.nextInt(10));

8 }

9 }

48304ba5e6f9fe08f3fa1abda7d326ab.png

现在,在创建Java源文件之后,我们可以使用名为DiagnosticCollector的诊断收集器类将诊断收集在列表中。

创建另一个类,从该类中我们将调用编译器来编译上述类MyClass,并将诊断信息报告给该类。换句话说,我们将创建一个应用程序来加载Java源文件,并由Java编译器对其进行编译,并且,如果源代码中有任何错误,请确保将其报告给主机应用程序。

48304ba5e6f9fe08f3fa1abda7d326ab.png

48304ba5e6f9fe08f3fa1abda7d326ab.png

1 package com.mano.jcapidemo;

2

3 import com.mano.annotation.CustomAnnotation;

4 import java.util.Set;

5 import javax.annotation.processing.AbstractProcessor;

6 import javax.annotation.processing.RoundEnvironment;

7 import javax.annotation.processing.SupportedAnnotationTypes;

8 import javax.annotation.processing.SupportedSourceVersion;

9 import javax.lang.model.SourceVersion;

10 import javax.lang.model.element.Element;

11 import javax.lang.model.element.ElementKind;

12 import javax.lang.model.element.TypeElement;

13 import javax.tools.Diagnostic;

14 @SupportedAnnotationTypes("com.mano.annotation.CustomAnnotation")

15 @SupportedSourceVersion(SourceVersion.RELEASE_10)

16 public class CustomAnnotationProcessor extends

17 AbstractProcessor {

18 public CustomAnnotationProcessor() {

19 } public Boolean process(Set extends

20 TypeElement> annotations,

21 RoundEnvironment roundEnv) {

22 for (Element e : roundEnv.getElementsAnnotatedWith

23 (CustomAnnotation.class)) {

24 if (e.getKind() != ElementKind.FIELD) {

25 processingEnv.getMessager().printMessage(

26 Diagnostic.Kind.WARNING,

27 "Not a field", e);

28 continue;

29 }

30 }

31 return true;

32 }

33 }

48304ba5e6f9fe08f3fa1abda7d326ab.png

48304ba5e6f9fe08f3fa1abda7d326ab.png

编译器依赖于两种服务:诊断侦听器和文件管理器。如果提供了侦听器,则将诊断信息提供给侦听器;否则,将向侦听器提供诊断信息。否则,诊断将以未指定的格式格式化,并定向到默认的错误输出系统(System.err)。默认情况下,编译器工具与标准文件管理器关联,并且可以与满足其要求的任何其他文件管理器一起正常工作。

注释处理器

编译过程还包括注释处理器。它执行编译由注释驱动的代码的附加过程。处理过程按一系列轮次进行,其中每个轮次处理其上一轮产生的注释子集。实现注释过程的接口是javax.annotation.processin.Processor。实现类必须提供一个无参数的构造函数,以供工具实例化处理器。处理基础结构应遵循某些协议,例如:

通过使用处理器类的无参数构造函数实例化注释处理器。

工具通过传递适当的ProcessingEnvironmentinstance实例来调用init方法。

这些工具调用由Processor接口定义的方法,例如getSupportedAnnotationTypes(), getSupportedOptions(), 和getSupportedSourceVersion()。这些方法在每次运行中调用一次,而不是在每个回合中调用一次。

最后,调用Processor对象上的process ()方法。

例如,简单的注释可以定义如下:

1 package com.mano.jcapidemo;

2 import java.lang.annotation.ElementType;

3 import java.lang.annotation.Target;

4 @Target(ElementType.FIELD)

5 public@interface CustomAnnotation {

6 }

一个非常简单的注释处理器,用于警告将注释应用于字段以外的任何其他元素,如下所示:

48304ba5e6f9fe08f3fa1abda7d326ab.png

1 package com.mano.jcapidemo;

2

3 import com.mano.annotation.CustomAnnotation;

4 import java.util.Set;

5 import javax.annotation.processing.AbstractProcessor;

6 import javax.annotation.processing.RoundEnvironment;

7 import javax.annotation.processing.SupportedAnnotationTypes;

8 import javax.annotation.processing.SupportedSourceVersion;

9 import javax.lang.model.SourceVersion;

10 import javax.lang.model.element.Element;

11 import javax.lang.model.element.ElementKind;

12 import javax.lang.model.element.TypeElement;

13 import javax.tools.Diagnostic;

14 @SupportedAnnotationTypes("com.mano.annotation.CustomAnnotation")

15 @SupportedSourceVersion(SourceVersion.RELEASE_10)

16 public class CustomAnnotationProcessor extends

17 AbstractProcessor {

18 public CustomAnnotationProcessor() {

19 } public Boolean process(Set extends

20 TypeElement> annotations,

21 RoundEnvironment roundEnv) {

22 for (Element e : roundEnv.getElementsAnnotatedWith

23 (CustomAnnotation.class)) {

24 if (e.getKind() != ElementKind.FIELD) {

25 processingEnv.getMessager().printMessage(

26 Diagnostic.Kind.WARNING,

27 "Not a field", e);

28 continue;

29 }

30 }

31 return true;

32 }

33 }

48304ba5e6f9fe08f3fa1abda7d326ab.png

SupportedAnnotationTypes定义注释处理器将处理哪种类型的注释,SupportedSourceVersion定义其支持的版本。 我们首先扩展AbstractProcessor抽象类,该类允许我们覆盖处理方法。 处理方法内部编写的逻辑完成了所有技巧,这些技巧涉及我们选择设置哪些标准来处理注释。 这最终决定了注释的含义。

元素扫描仪

元素扫描器在编译过程中对所有语言元素执行分析。它根据访问者模式构建,以根据源版本的发布情况,以默认行为扫描程序元素。例如,ElementScanner9根据源版本RELEASE_9和RELEASE_10进行扫描,而ElementScanner8分别根据源版本RELEASE_8进行扫描。这两个类都可以在javax.lang.model.utilpackage中找到。

编译树API Compiler Tree API

有时,有必要将整个Java源文件解析为抽象语法树,尤其是为了进行更深入的分析。Java编译器树API遵守该要求,并与javax.lang.model包紧密关联。它以与元素扫描器相同的模式构建,并且以类似的方式工作。密钥类称为TreePathScanner。它访问所有子树节点,并有助于维护到父节点的路径。要访问特定节点,我们可以简单地覆盖相应的visitorXYZ方法。

总结

Java编译器API从Java应用程序中提供对Java编译器的编程访问。显而易见,此API有更深层的含义,在这里我们只涉及了其中的内容。但是,此快速介绍可能会提供有关在开始使用Java Compiler API时要查找的内容的线索。

参考

Java API文档


http://www.ppmy.cn/news/248337.html

相关文章

selenium(java)教程学习(附带全部代码)

java web自动化 javaseleniumtestngJenkins 想要使用Selenium实现web自动化测试,主要需要的东西。 1.需要安装jdk,配置jdk,(selenium3需要jdk1.8以上) 2. 安装eclipse(编写工具) 3. 安装webdrve…

台式计算机和便携式计算机是替代品吗,iPad能否替代笔记本电脑?这结果我一万个不服!...

近年来,随着平板电脑的不断发展,有一个长期存在的问题,平板(文中主要指iPad)是否可以替代传统笔记本电脑? 平板电脑和笔记本电脑如今可以做很多事情,最好的平板电脑甚至比一些笔记本电脑功能更强大,但它是一…

java 获取数组值_java获取数组值的数量

我已经有了以下代码 public class Qn3 { static BigDecimal[] accbal new BigDecimal[20]; private static Integer[] accnums new Integer[5]; public static void main(String[] args) { int count; accnums {1,2} //i cant add this line of code as well, what is wrong?…

阿里P8整理总结,入职大厂必备Java核心知识(附加面试题

前言 今天就给大家分享一波一位小伙伴面试大厂的经历、知识点和面试题分享,主要内容包括:JVM、JAVA集合、JAVA多线程并发、JAVA基础、Spring原理、微服务、Netty与RPC、网络、日志、 Zookeeper、 Kafka、 RabbitMQ、 Hbase、 MongoDB、 Cassandra、设计模…

在线flash转html5,Safari插件推荐:自动转Flash为Html5

给大家推荐一款很给力Mac系统Safair浏览器插件,它能够自动将网页上的Flash视频转换成HTML5播放,能够很大程度上节省CPU损耗,同时也使得MacBook风扇温度降低。 替换国内各大网站flash播放器为Html5播放器,减少CPU占用率&#xff0c…

领域驱动设计在爱奇艺打赏业务的实践

领域驱动设计(Domain-Driven Design,以下简称DDD)思潮的形成要追述到30几年前,17年前,Eirc Evans定义了领域驱动设计的概念。DDD一直为传统行业的软件工程师提供软件设计的方法论,但是在互联网行业却使用很少。直到近几年&#xf…

从 Spark Streaming 到 Apache Flink : 实时数据流在爱奇艺的演进

作者:陈越晨 整理:刘河 本文将为大家介绍Apache Flink在爱奇艺的生产与实践过程。你可以借此了解到爱奇艺引入Apache Flink的背景与挑战,以及平台构建化流程。主要内容如下: 爱奇艺在实时计算方面的的演化和遇到的一些挑战爱奇艺…

领域驱动设计(DDD)在爱奇艺打赏业务的实践

领域驱动设计(Domain-Driven Design,以下简称DDD)思潮的形成要追述到30几年前,17年前,Eirc Evans定义了领域驱动设计的概念。DDD一直为传统行业的软件工程师提供软件设计的方法论,但是在互联网行业却使用很少。直到近几年&#xf…