定义 -> @interface
publiC @interface TestAnnotation{
}
应用
@TestAnnotation
public class Test{
}
元注解
基本注解,而且可以注解到注解上.
@Retention、@Documented、@Target、@Inherited、@Repeatable
Retention -> 解释注解的存活时间
- 取值:
RetentionPolicy.SOURCE
: 编译时忽略它RetentionPolicy.CLASS
: 编译时保留,但不加载到jvm
中RetentionPolicy.RUNTIME
: 加载进JVM
, 程序运行时还在@Retention(RetentionPolicy.RUNTIME)
public @interface TestAnnotation {
}
- 取值:
Document -> 将注解中的元素加到
Javadoc
里- Target -> 指定了注解运用的地方
- ElementType.ANNOTATION_TYPE 可以给一个注解进行注解
- ElementType.CONSTRUCTOR 可以给构造方法进行注解
- ElementType.FIELD 可以给属性进行注解
- ElementType.LOCAL_VARIABLE 可以给局部变量进行注解
- ElementType.METHOD 可以给方法进行注解
- ElementType.PACKAGE 可以给一个包进行注解
- ElementType.PARAMETER 可以给一个方法内的参数进行注解
- ElementType.TYPE 可以给一个类型进行注解,比如类、接口、枚举
- Inherited -> 说如果一个超类被 @Inherited 注解过的注解进行注解的话,那么如果 它的子类没有被任何注解应用的话,那么这个子类就继承了超类的注解。
- Repeatable -> 让注解可以在同一地方出现多次
@interface Persons {
Person[] value();
}
@Repeatable(Persons.class)
@interface Person{
String role default "";
}
Repeatable
注解了Person
,Persons.class
是容器注解(存放容器的地方), 它里面必须有一个叫value
的属性,类型是一个数组, 放的是被@Repeatable注解过的注解…
然后就可以让注解可以在同一地方出现多次了@Person(role="artist")
@Person(role="coder")
@Person(role="PM")
public class SuperMan{
}
注解的属性
注解只有属性没有方法
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TestAnnotation {
int id() default -1;
String msg() default "Hi";
}
可以以 实例.id()
的格式调用
赋值:(不赋值就是 default
)
@TestAnnotation(id=3,msg="hello annotation")
public class Test {
}
只有一个属性的话就不用了写 value = xx
了, 直接写 xx
就行了
@Check("hi")
int a;
最后,还需要注意的一种情况是一个注解没有任何属性。比如
public @interface Perform {}
那么在应用这个注解的时候,括号都可以省略。
@Perform
public void testMethod(){}
预置注解
- Deprecated -> 标记过时的元素,编译器识别后会产生”划掉”效果
- Override -> 提示子类要重写父类中被 @Override 修饰的方法
SupperWarnings -> 忽略警告, 比如”忽略方法过时的警告”:
@SuppressWarnings("deprecation")
-
提取注解
如果一个注解要在运行时被成功提取,那么@Retention(RetentionPolicy.RUNTIME) 是必须的
注解通过反射获取。首先可以通过 Class 对象的 isAnnotationPresent() 方法判断它是否应用了某个注解
public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {}
然后通过 getAnnotation() 方法来获取 Annotation 对象。
public <A extends Annotation> A getAnnotation(Class<A> annotationClass) {}
或者是 getAnnotations() 方法。
public Annotation[] getAnnotations() {}
前一种方法返回指定类型的注解,后一种方法返回注解到这个元素上的所有注解。
例子:
@TestAnnotation()
public class Test {
public static void main(String[] args) {
boolean hasAnnotation = Test.class.isAnnotationPresent(TestAnnotation.class);
if ( hasAnnotation ) {
TestAnnotation testAnnotation = Test.class.getAnnotation(TestAnnotation.class);
System.out.println("id:"+testAnnotation.id());
System.out.println("msg:"+testAnnotation.msg());
}
}
}
属性/方法上的注解
@TestAnnotation(msg="hello")
public class Test {
@Check(value="hi")
int a;
@Perform
public void testMethod(){}
@SuppressWarnings("deprecation")
public void test1(){
Hero hero = new Hero();
hero.say();
hero.speak();
}
public static void main(String[] args) {
boolean hasAnnotation = Test.class.isAnnotationPresent(TestAnnotation.class);
if ( hasAnnotation ) {
TestAnnotation testAnnotation = Test.class.getAnnotation(TestAnnotation.class);
//获取类的注解
System.out.println("id:"+testAnnotation.id());
System.out.println("msg:"+testAnnotation.msg());
}
try {
Field a = Test.class.getDeclaredField("a");
a.setAccessible(true);
//获取一个成员变量上的注解
Check check = a.getAnnotation(Check.class);
if ( check != null ) {
System.out.println("check value:"+check.value());
}
Method testMethod = Test.class.getDeclaredMethod("testMethod");
if ( testMethod != null ) {
// 获取方法中的注解
Annotation[] ans = testMethod.getAnnotations();
for( int i = 0;i < ans.length;i++) {
System.out.println("method testMethod annotation:"+ans[i].annotationType().getSimpleName());
}
}
} catch (NoSuchFieldException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println(e.getMessage());
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println(e.getMessage());
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println(e.getMessage());
}
}
}