注解(Annotation)是从jdk1.5开始增加的特性。学习注解能够读懂框架的代码;让编程更加简洁,代码更加清晰。
注解概念:java提供了一种原程序中的元素关联任何信息和任何元数据的途径和方法。
注解需要import java.lang.annotation.*;
java自带的3个注解:
- @Override//覆盖
- @Deprecated//过时
- @SuppressWarnings()//抑制警告
自定义注解的语法要求
一般自定义注解的代码如下://“Description 注解”在下面的栗子中会用到哦O(∩_∩)O
@Target({ElementType.METHOD,ElementType.TYPE})//作用域是在方法上、类或者接口上。
@Retention(RetentionPolicy.RUNTIME)
@Inherited//允许子类继承(你给某个父类注解了,子类会继承父类的注解)
@Documented//生成doc时会包含注解的信息
public @interface Description {//使用@interface关键字定义注解
String desc();//成员以无参无异常方式声明
String author();
int age() default 18;//可以用default为成员制定一个默认值
}
讲解:
元注解,就是注解的注解,@Target, @Retention, @Inherited, @Documented都是元注解。
@Target的取值有:
- ElementType.TYPE //接口、类、枚举、注解
- ElementType.FIELD/字段、枚举的常量
- ElementType.METHOD//方法
- ElementType.PARAMETER//方法参数
- ElementType.CONSTRUCTOR//构造函数
- ElementType.LOCAL_VARIABLE//局部变量
- ElementType.ANNOTATION_TYPE//注解
- ElementType.PACKAGE///包
Retention:保留,定义注解的保留策略。有3个值:SOURCE、CLASS、RUNTIME。
- SOURCE只在源码显示,编译时会丢弃。
- CLASS编译时会记录到class中,运行时忽略。
- RUNTIME运行时存在,可以通过反射读取。在执行main方法就是运行时。
成员类型是受限的,合法的类型包括原始类型及String,Class,Annotation, Enumeration。
当注解只有一个成员时,成员名必须取名为value(),因为约定俗成,我们可以不用写参数名和赋值号。直接给参数值。简洁方便。允许你偷看下面的注解类MyDescription。
注解类可以没有成员,没有成员的注解称为标识注解。如SpringMVC里面的@Controller,就是标识注解。
解析注解:通过反射获取类、函数或成员上的运行时注解信息,从而实现动态控制程序运行的逻辑。
1 package com.rainmer.anno; 2 3 import java.lang.annotation.*; 4 5 /** 6 * Created by Simon Sun on 2015/7/22. 7 */ 8 @Target({ElementType.METHOD,ElementType.TYPE}) 9 @Retention(RetentionPolicy.RUNTIME) 10 @Inherited 11 @Documented 12 public @interface MyDescription { 13 public String value(); 14 }
1 package com.rainmer.anno; 2 3 /** 4 * Created by Simon Sun on 2015/7/22. 5 */ 6 @MyDescription("i am interface") 7 public interface Person { 8 @MyDescription("i am interface method") 9 public String name(); 10 public int age(); 11 public void sing(); 12 }
1 package com.rainmer.anno; 2 3 /** 4 * Created by Simon Sun on 2015/7/22. 5 */ 6 @MyDescription("i am a class annotation") 7 public class Child implements Person { 8 @Override 9 @MyDescription("i am a method annotation") 10 @Description(desc = "the name method",author = "mook boy") 11 public String name() { 12 return null; 13 } 14 15 @Override 16 public int age() { 17 return 0; 18 } 19 20 @Override 21 public void sing() { 22 23 } 24 }
1 package com.rainmer.anno; 2 3 import java.lang.annotation.Annotation; 4 import java.lang.reflect.Method; 5 6 /** 7 * Created by Simon Sun on 2015/7/22. 8 */ 9 public class ParseAnno { 10 public static void main(String[] args) { 11 //1、使用类加载器加载类 12 try { 13 Class c = Class.forName("com.rainmer.anno.Child"); 14 //判断雷尚是否有MyDescription这样的注解 15 boolean isExist = c.isAnnotationPresent(MyDescription.class); 16 if(isExist){ 17 //3、拿到注解实例 18 MyDescription myDescription = (MyDescription) c.getAnnotation(MyDescription.class); 19 System.out.println(myDescription.value()); 20 } 21 22 //4、找到方法上的注解 23 Method[] ms = c.getMethods(); 24 for(Method m : ms){ 25 boolean isMExist = m.isAnnotationPresent(MyDescription.class); 26 if(isMExist){ 27 MyDescription d = m.getAnnotation(MyDescription.class); 28 System.out.println(d.value()); 29 } 30 } 31 32 //另外一种解析方法 33 for(Method m : ms){ 34 Annotation[] as = m.getAnnotations(); 35 for(Annotation a : as){ 36 if(a instanceof MyDescription){ 37 MyDescription d = (MyDescription) a; 38 System.out.println(d.value()); 39 } 40 } 41 } 42 } catch (ClassNotFoundException e) { 43 e.printStackTrace(); 44 } 45 46 } 47 }
程序输出:
i am a class annotation
i am a method annotation
i am a method annotation
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
继承的时候不仅会继承类的注解,也会继承方法的注解,前提是子类不覆盖父类的方法。
来个栗子:
1 package com.rainmer.anno; 2 3 /** 4 * Created by Simon Sun on 2015/7/22. 5 */ 6 @MyDescription("i am parent class") 7 public class Animal { 8 @MyDescription("i am parent method") 9 public String getName(){ 10 return null; 11 }; 12 }
1 package com.rainmer.anno; 2 3 /** 4 * Created by Simon Sun on 2015/7/22. 5 */ 6 public class Dog extends Animal { 7 8 }
解析类ParseAnno只要修改第13行为:Class c = Class.forName("com.rainmer.anno.Dog");即可。
程序输出:
i am parent class
i am parent method
i am parent method
但是如果Dog覆盖了getName方法,那么输出就变成:
i am parent class
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
最后加点调料,idea的两个实用快捷键:
alt+回车:add exception或者快速try/catch;强制类型转换 。
alt+insert:生成代码,如get、set方法,构造函数等,当然,还可以用来快速覆盖接口或父类的方法
源码下载:http://yunpan.cn/ccWaszMAARdJb 访问密码 d806