Java基础知识-注解

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保留时间。

  • RetentionPolicy.CLASS 默认值

    注解记录在class文件中,jvm不可获取注解信息

  • RetentionPolicy.RUNTIME

    注解记录在class文件中,jvm可获取注解信息,程序也可以反射获取注解信息

  • RetentionPolicy.SOURCE

    注解记录在源代码中,编译器直接丢弃该注解

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异常
本文结束  感谢您的阅读
  • 本文作者: Wang Ting
  • 本文链接: /zh-CN/2019/09/19/Java基础知识-注解/
  • 发布时间: 2019-09-19 01:12
  • 更新时间: 2021-10-29 14:21
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!