什么是注解
注解相当于一种标记,开发工具、编译器、JVM可以通过反射来了解类和元素有没有注解,
然后去做出相应的操作。
例如 重写方法时加上@Override注解,编译器就会检查该方法有没有正确的覆盖方法
修饰注解的注解:元注解
Retention注解
Retention注解用于限制注解信息保留的阶段
@Retention注解有一个属性value是RetentionPolicy类型的。
RetentionPolicy 有3个枚举值:SOURCE CLASS RUNTIME
* @RetentinoPolicy(RetentionPolicy.SOURCE) 修饰注解时,该注解的信息只会保留
在源文件中,不会保留在class文件中,也不会被jvm读取到运行时
* @RetentionPolicy(RetentionPolicy.CLASS) 修饰注解时,该注解的信息会保留在
class文件中,但是不会被jvm读取
* @RetentionPolicy(RetentionPolicy.RUNTIME) 修饰注解时,该注解的信息会被保留
在class文件中,也会被jvm读取从而保留到运行时
Target注解
Target注解限定注解适用的类型
Target的value属性是一个ElementType枚举类。
枚举值有7个:
1. ElementType.CONSTRUCTOR —注解可以用于构造器
2. ElementType.FIELD —注解可以用于域声明
3. ElementType.LOCAL_VARIABLE — 注解可以用于局部变量声明
4. ElementType.METHOD — 注解可以用于方法声明
5. ElementType.PACKAGE — 注解可以用于包声明
6. ElementType.PARAMETER — 注解可以用于参数
7. ElementType.TYPE —注解可以用于类、接口、注解类型、enum声明
Documented注解
Documented注解表明制作javadoc时,是否将注解信息加入文档。如果注解在声明时
使用了@Documented,则在制作javadoc时会将注解信息加入javadoc.
Inherited注解
表明注解是否会被子类继承。默认情况子类不继承父类注解。
当一个注解加了@Inherited元注解后,该注解会被使用了该注解的子类继承
自定义注解的方法
定义注解类型跟一个定义一个接口类似
在interface关键字前面加一个@符号
注释中的每一个方法定义了这个注释类型的一个元素,
注释中方法的声明中一定不能包含参数,也不能抛出异常。
方法的返回值被限定为基本类型、String、Class、enums、注释以及这些类型的数组类型
方法可以有缺省值
自定义注解的例子
public @interface RequestForEnhancement{
int id();
String synopsis();
String engineer() default "[unassigned]";
String date(); default "[unimplemented]";
}
注解的用法:
@后面加注解名字,后面再跟上括号,括号中列出这个注释中的元素以及对应
的值的列表。键值对中的值必须是常量。
使用注解的例子
@RequestForEnhancement{id=20142480117,synopsis="Enable time-travel",engineer="Mr.liu",date="4/1/3007"}
标记型注解
如果注解没有元素,则该注解为标记型注解(maker)。
标记型注解例子:
public @interface Test{}
在使用标记型注解时,后面的括号可以忽略。
只有一个元素的注解
如果注解只有一个元素,则该元素的名字应该为value
使用该注解时元素的名字和等号可以省略
用自定义注解实现一个简单的测试框架
- 定义注解Test
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Test{}
- 在要测试的方法上加@Test注解
public claass TestCase{
@Test
public static void test1(){}
@Test
public static void test2(){
System.out.println("test2");
}
}
import java.lang.reflect.*;
public class TestCaseRun{
public static void main(String args[]){
Class clazz=TestCase.class;
Method[] methods=clazz.getMethods();
for(Method m:methods){
if(m.isAnnotationPresent(Test.class){
try{
m.invoke(null);
}catch(Throwable ex){
System.out.println(ex.getCause());
}
}
}
}
}