脚本API
在java中可以调用其他脚本语言写代码,比如JavaScript,Groovy,Ruby。一般需要引入两个jar包集合,一个是脚本语言自身的jar包集合,一个是该脚本语言的脚本引擎jar包
编译API
除了可以使用javac编译工具进行编译源文件,还可以在程序运行中调用编译API进行编译代码,而且代码不仅可以是来自文件,也可以是来自其他地方,比如StringBuffer。最简单的API是JavaCompiler的run方法,如果想要控制更多的编译过程的细节,可以使用CompilationTask类,不过比较复杂,可以控制程序代码的来源,比如在StringBuffer;可以控制类文件的位置,比如存到数据库;可以监听编译过程中的错误和警告信息,可以在后台运行编译器。源码的位置和类文件的位置是由JavaFileManager控制的,位置用JavaFileObject类来表示,JavaFileObject可以表示磁盘的文件,也可以对应其他位置
注解
注解本身并不会做任何事情,它需要工具的支持(需要对应的工具来处理),在一个地方打注解,相当于在这个地方打个标记,注解对应的工具来处理。所有的注解接口都隐式地扩展自java.lang.annotation.Annotation,而Annotation是一个常规接口,不是注解接口,注解接口无法被扩展
- 定义注解
注解是由注解接口来定义的,一般定义的形式如下
modifiers @interface AnnotationName {
elementDeclaration1
elementDeclaration2
...
}
每个元素声明都形如type elementName();
或者type elementName() default value;
,例如
@Target({ElementType.Method})
public @interface BugReport {
String assignedTo() default "none";
int level() = 0;
}
使用注解的时候如果不指定元素值,就会使用默认值(也可能是该注解没有声明元素),比如
@BugReport(assignedTo="Alice", level = 2)
public void f() {
...
}
- 元注解
@Target应用于注解的定义上,限制该注解可以运用于哪些项上,如果在定义一个注解的时候,没有使用@Target,则该注解可以运用于任何项。
类别 | 描述 |
---|---|
ElementType.ANNOTATION_TYOE | 注解类型声明 |
ElementType.PACKAGE | 包 |
ElementType.TYPE | 类,枚举和接口 |
ElementType.METHOD | 方法 |
ElementType.CONSTRUCTOR | 构造器 |
ElementType.FIELD | 字段 |
ElementType,PARAMETER | 方法或构造器参数 |
ElementType.LOCAL_VARIABLE | 局部变量 |
@Retention
用于指定注解应该保存的时间(或阶段)
类别 | 描述 |
---|---|
SOURCE | 只保留在源码中 |
CLASS | 源码和类文件中都保留,但虚拟机不将注解载入 |
RUNTIME | 源码和类文件中都保留,虚拟机会载入注解 |
@Documented
表示是否归档
@Inherited
有@Inherited的注解只能用在类上,表示该注解能被子类继承,在类A上使用这种注解,那么A的子类自动会继承这个注解,比如@Serializable
如何获取注解对象并进行处理
思路:比如某个注解,名为BugReport,是用在方法上的,那么我们获得一个对象后,然后获得对象的Class对象,然后通过getDeclaredMethods()获得Method集合,然后遍历该Method集合,对每个Method对象调用BugReport br = m.getAnnotation(BugReport.class)
,如果在该方法上使用了注解,那么就会返回一个注解对象,否则返回null。然后我们就可以决定怎么处理了。对于在其他项上的注解,同样可以使用这个思路
注解的使用
注解可以在源码阶段,字节码阶段,运行阶段做事情