java注解(一)
什么是注解?
注解(Annotation)是JDK5的新特性,是一种特殊的类,作用类似于注释,相当于是一个标记,可以标记在一个类身上的不同位置,可以修饰不同的成员变量、方法甚至是类。
简单来说: 就是相当于一些类似于注释的信息 和 源程序中的元素 绑定的一种技术,这种技术叫做注解。
这种手段可以通过反射获取到元素对象,在获取到这个元素上面绑定的注解,通过绑定的注解获取里面配置信息,
从而达到能够在程序运行阶段通过这些信息动态地改变程序的运行逻辑。
为什么使用注解?
- 1.能够灵活地使用框架提供的注解,最后能够读懂框架的源码
- 2.能够配合反射将代码书写更加的灵活,更加易于维护易于扩展,Properties配置,XML配置,注解配置[Java配置]
- 3.极大程度地简化了代码,提高了代码的可读性
怎么使用注解?
自定义注解并且使用
四种使用注解的方式:
格式一: @注解的名称(属性名1=属性值1,属性名2=属性值2,属性名3=属性值3,...属性名n=属性值n)
注意: 如果有两个以上的属性,有多少个属性就必须给多少个属性赋值
格式二: 适用于注解只有一个成员
@注解的名称(属性值)
格式三: 适用于成员是数组的情况
@注解的名称({属性值1,属性值2,属性值3,...属性值n})
格式四: 使用标记注解
@注解的名称
下面列举开发中常见的注解
- @Override:用于标识该方法继承自超类, 当父类的方法被删除或修改了,编译器会提示错误信息(我们最经常看到的toString()方法上总能看到这货)
- @Deprecated:表示该类或者该方法已经不推荐使用,已经过期了,如果用户还是要使用,会生成编译的警告
- @SuppressWarnings:用于忽略的编译器警告信息
@Override注解源码
1 @Target(ElementType.METHOD)
2 //ElementType元素类型指定注解的类型
3 //可以存放的位置 TYPE,FIELD,METHOD,PARAMETER,CONSTRUCTOR,LOCAL_VARIABLE,ANNOTATION_TYPE,PACKAGE,
4 @Retention(RetentionPolicy.SOURCE)
5 public @interface Override {
6 }
RetentionPolicy的源码
RetentionPolicy是个枚举类,可以设置三种情况的注解,源码时期的注解,编译时期的注解,运行时期的注解
1 public enum RetentionPolicy {
2 /**
3 * Annotations are to be discarded by the compiler.
4 */
5 SOURCE,
6
7 /**
8 * Annotations are to be recorded in the class file by the compiler
9 * but need not be retained by the VM at run time. This is the default
10 * behavior.
11 */
12 CLASS,
13
14 /**
15 * Annotations are to be recorded in the class file by the compiler and
16 * retained by the VM at run time, so they may be read reflectively.
17 *
18 * @see java.lang.reflect.AnnotatedElement
19 */
20 RUNTIME
21 }
注解实例
1 public class AnnotationDemo01 {
2 public static void main(String[] args) {
3
4 }
5 }
6
7 // 希望当前注解MyAnnotation可以用在类,接口,构造方法,方法上
8 @Target({ ElementType.TYPE, ElementType.CONSTRUCTOR, ElementType.METHOD })
9 // 希望当前注解MyAnnotation可以在运行时有效
10 @Retention(RetentionPolicy.RUNTIME)
11 // 希望当前注解可以在子类中生效
12 @Inherited
13 // 希望当前注解可以在API文档中生成
14 @Documented
15 @interface MyAnnotation {
16 String desc();
17
18 int val() default 0;
19
20 String[] hobbys();
21 }
22
23 @Target({ ElementType.FIELD })
24 @Retention(RetentionPolicy.RUNTIME)
25 @interface Column {
26 String value();
27 }
28
29 @Target({ ElementType.FIELD })
30 @Retention(RetentionPolicy.RUNTIME)
31 @interface PrimaryKey {
32 boolean isAutoIncrease();
33 String name();
34 }
35
36 @Target({ ElementType.TYPE })
37 @Retention(RetentionPolicy.RUNTIME)
38 @Inherited
39 @interface Fu {
40
41 }
42
43 @Fu
44 class Person {
45
46 }
47
48 @MyAnnotation(desc = "Student Class", val = 18, hobbys = { "篮球", "足球", "乒乓球" })
49 class Student extends Person {
50
51 @Column("sid")
52 @PrimaryKey(isAutoIncrease = true, name = "sid")
53 private String id;
54 @Column("sname")
55 private String name;
56 @Column("sage")
57 private int age;
58
59 public Student() {
60 super();
61 }
62
63 public Student(String name, int age) {
64 super();
65 this.name = name;
66 this.age = age;
67 }
68
69 @Override
70 @MyAnnotation(desc = "1111", val = 18, hobbys = { "篮球", "足球", "乒乓球" })
71 public String toString() {
72 return "Student [name=" + name + ", age=" + age + "]";
73 }
74
75 public String getName() {
76 return name;
77 }
78
79 public void setName(String name) {
80 this.name = name;
81 }
82
83 public int getAge() {
84 return age;
85 }
86
87 public void setAge(int age) {
88 this.age = age;
89 }
90
91 }
注解与反射
注解很多时候会和反射一起用,用于底层框架编写的时候。
使用反射解析注解:
- 1.使用反射解析类或者接口或者枚举上面的注解,必须先要获取到字节码文件对象
- 2.解析除了类上的注解外,必须先获取到元素对象
- 3.获取注解之前一定要做存在性判断
为什么? 因为如果是源码或者编译时注解,那么反射是在运行时获取,注解在运行时已经不存在就获取不到
通过反射获取注解元素的相关方法:
- <A extends Annotation> A getAnnotation(Class<A> annotationClass)
- Annotation[] getAnnotations()
- Annotation[] getDeclaredAnnotations()
- boolean isAnnotationPresent(Class<? extends Annotation> annotationClass)
1 public class AnnotationDemo02 {
2 public static void main(String[] args) throws Exception {
3 // 获取学生类上的注解: @MyAnnotation
4 Class<?> c = Class.forName("com.sxt.annotationdemo02.Student");
5 // 获取到id上面注解绑定的信息
6 Field idField = c.getDeclaredField("id");
7 Annotation[] annotations = idField.getAnnotations();
8 for (Annotation annotation : annotations) {
9 if (annotation instanceof Column) {
10 Column column = (Column) annotation;
11 System.out.println(column.value());
12 } else if(annotation instanceof PrimaryKey) {
13 PrimaryKey primaryKey = (PrimaryKey) annotation;
14 System.out.println(primaryKey.isAutoIncrease() + "|" + primaryKey.name());
15 }
16 }
17
18 Method toStringMethod = c.getMethod("toString");
19 if (toStringMethod.isAnnotationPresent(MyAnnotation.class)) {
20 MyAnnotation annotation = toStringMethod.getAnnotation(MyAnnotation.class);
21 if (annotation != null) {
22 String desc = annotation.desc();
23 System.out.println(desc);
24 }
25 }
26 }
27
28 }