Annotation不同于注释,可以在编译,类加载时被读取,反射可以得Annotation对象,从而得元数据
1. 基本注解
1.1. @Override 重写父类方法
只作为修饰方法,限定重写父类方法
1.2. @Deprecated
已过时
1.3. @SuppressWarnings
取消显示编译器警告
1
| @SuppressWarnings(value="unchecked")
|
1.4. @SafeVarargs
不带泛型的对象赋给一个带泛型的变量而产生堆污染,@SafeVarargs抑制警告
1.5. @FunctionalInterface
指定某个接口必须是函数式接口。保证接口只能包含一个抽象方法。
2. 修饰元Annotation
2.1. @Retention
修饰Annotation定义,指定Annotation保留时间。
1 2
| @Retention(value=RetentionPolicy.RUNTIME) public @interface Test(){ }
|
2.2. @Target
修饰注解,指定被修饰注解能用于修饰哪些程序单元
- ElementType.ANNOTATION_TYPE 注解
- ElementType.CONSTRICTOR 构造器
- ElementType.FIELD 成员变量
- ElementType.LOCAL_VARIABLE 局部变量
- ElementType.METHOD 方法
- ElementType.PARAMETER 参数
- ElementType.PACKAGE 包
- ElementType.TYPE 类,接口,枚举定义
2.2.1. 类型注解
TYPE_PARAMETER:注解能写在类型变量的声明语句中
TYPE_USE:注解能写在使用类型的任何语句中
1 2 3 4 5 6 7
| @Target({ElementType.TYPE_PARAMETER,ElementType.TYPE_USE}) public @interface Season { }
class Main<@Season T>{ ArrayList<@Season Integer> list = new ArrayList<>(); }
|
2.3. @Documented
使用该注解修饰的程序元素的API文档中会包含该注解说明。
2.4. @Inherited
注解具有继承性,类使用@Xxx注解,子类也会自动用@Xxx
2.5. @Repeatable
可重复定义
1 2 3 4 5 6 7 8 9 10 11 12 13
| public @interface MyAnnotations { Season[] value(); }
@Repeatable(MyAnnotations.class) public @interface MyAnnotation {
}
@MyAnnotation @MyAnnotation void testSystem() { }
|
3. 自定义注解
1 2 3 4 5 6 7
| public @interface mytag{ String name(); int age(); }
@mytag(name="",age=1) public void info(){}
|
定义初始值
1 2 3 4
| public @interface mytag{ String name() default ""; int age() default 1; }
|
4. 提取注解信息– 反射
注解
SxtTable.java
1 2 3 4 5 6 7 8 9 10 11
| import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;
@Target(value= {ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface SxtTable { String value(); }
|
SxtField.java
1 2 3 4 5 6 7 8 9 10 11 12 13
| import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;
@Target(value= {ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) public @interface SxtField { String columnName(); String type(); int length(); }
|
SxtAnnotation.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| @SxtTable(value="Student") public class SxtAnnotation {
@SxtField(columnName = "id", length = 6, type = "int") private int id; private String name; private int age; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "SxtAnnotation [id=" + id + ", name=" + name + ", age=" + age + "]"; } }
|
反射
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| import java.lang.annotation.Annotation; import java.lang.reflect.Field;
public class ClassTest {
public static void main(String[] args) { try { Class clazz = Class.forName("SxtAnnotation"); Annotation[] all = clazz.getAnnotations(); for (Annotation annotation : all) { System.out.println(annotation); } SxtTable table = (SxtTable)clazz.getAnnotation(SxtTable.class); Field field = clazz.getDeclaredField("id"); SxtField f = field.getAnnotation(SxtField.class); System.out.println(f.columnName()+"\t"+f.type()+"\t"+f.length()); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } } }
|
5. 反射-注解-测试
5.1. 注解Check
1 2 3 4 5 6 7 8 9 10
| import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface Check {
}
|
5.2. 被测试类
1 2 3 4 5 6 7 8 9 10 11
| public class Main {
@Check public void div(int a,int b){ System.out.println(a/b); }
public void add(int a,int b){ System.out.println(a+b); } }
|
5.3. 测试类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; import java.lang.reflect.Method;
public class Test { public static void main(String[] args) throws IOException { Main m = new Main(); Class c = m.getClass();
BufferedWriter writer = new BufferedWriter( new FileWriter(System.getProperty("user.dir")+"/src/debug.txt")); int num = 0;
Method[] methods = c.getMethods(); for(Method method:methods){ if (method.isAnnotationPresent(Check.class)){ try{ method.invoke(m,1,0); }catch (Exception e){ num++; writer.write(method.getName()+" 出现异常:"); writer.newLine(); writer.write("异常类型:"+e.getCause().getClass().getSimpleName()); writer.newLine(); writer.write("异常信息:"+e.getCause().getMessage()); writer.newLine(); writer.write("======================="); writer.newLine(); writer.flush(); } } } writer.write("共出现了"+num+"异常"); writer.newLine(); writer.close();
} }
|
5.4. debug.txt
1 2 3 4 5
| div 出现异常: 异常类型:ArithmeticException 异常信息:/ by zero ======================= 共出现了1异常
|