总结
1.注解只是相当于一种标识,标志着被修饰的类,方法,属性等应该具有的公共的功能。这一点可以从注解的源码看 出来,注解的源码只有属性变量,并没有方法;这些属性变量的不同取值映射为不同的功能
2.通过反射解析出注解的属性值,并根据属性值是否为指定的值,来判断是否执行相关代码
1:Java中常见注解
详细介绍:基本内置注解
- @Override
用在方法上,表示这个方法重写了父类的方法,如toString()。 - @Deprecated
表示这个方法已经过期,不建议开发者使用。(暗示在将来某个不确定的版本,就有可能会取消掉) - @SafeVarargs
参数安全类型注解。它的目的是提醒开发者不要用参数做一些不安全的操作,它的存在会阻止编译器产生 unchecked 这样的警告 - @FunctionalInterface
用于约定函数式接口。 如果接口中只有一个抽象方法(可以包含多个默认方法或多个static方法),该接口称为函数式接口。函数式接口其存在的意义,主要是配合Lambda 表达式 来使用。
2: 注解分类
按运行机制分:
- 源码注解
注解只在源码中存在,编译成.class文件就不存在了 - **编译时注解 **
注解在源码和.class文件中都会存在。比如说@Override - **运行时注解 **
在运行阶段还会起作用,甚至会影响运行逻辑的注解。比如说@Autowired
3:自定义注解
- **自定义注解的语法要求 **
package grammar;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @Description 自定义注解的语法要求
* @since 2018年10月29日 下午4:47:07
* @author
*/
/***************** 元注解 **********************************/
/*@Target 表示这个注解能放在什么位置上,是只能放在类上?还是即可以放在方法上,又可以放在属性上
*
* ElementType.TYPE:能修饰类、接口或枚举类型
ElementType.FIELD:能修饰成员变量
ElementType.METHOD:能修饰方法
ElementType.PARAMETER:能修饰参数
ElementType.CONSTRUCTOR:能修饰构造器
ElementType.LOCAL_VARIABLE:能修饰局部变量
ElementType.ANNOTATION_TYPE:能修饰注解
ElementType.PACKAGE:能修饰包
* */
@Target({ElementType.METHOD , ElementType.TYPE})
/*@Retention
* 表示生命周期,
*
* RetentionPolicy.SOURCE: 注解只在源代码中存在,编译成class之后,就没了。@Override 就是这种注解
*
* RetentionPolicy.CLASS: 注解在java文件编程成.class文件后,依然存在,但是运行起来后就没了
* @Retention的默认值,即当没有显式指定@Retention的时候,就会是这种类型。
*
* RetentionPolicy.RUNTIME: 注解在运行起来之后依然存在,程序可以通过反射获取这些信息
*
* */
@Retention( RetentionPolicy.RUNTIME)
/*@Inherited 表示该注解具有继承性
如果一个超类被 @Inherited 注解过的注解进行注解的话,那么如果它的子类没有被任何注解应用的话,那么这个子类就继承了超类的注解。*/
@Inherited
//元注解肯定是和文档有关。它的作用是能够将注解中的元素包含到 Javadoc 中去
@Documented
//使用 @interface 关键字定义注解
public @interface Description {
/* 成员变量
* 1. 注解的定义中以“无形参的方法”形式来声明,其方法名定义了该成员变量的名字,其返回值定义了该成员变量的类型
*
* 2. 注解中定义属性时它的类型必须是 8 种基本数据类型外加 类、接口、注解及它们的数组
*
* 3. 如果注解只有一个成员,则成员名必须取名为 value() ,在使用时可以忽略成员名和赋值号(=)
*
* 4. 注解类可以没有成员,没有成员的注解称为标识注解
* */
String desc();
String author();
//可以用 default 为成员指定一个默认的值
int age() default 18;
}
- **使用自定义注解 **
@<注解名>(<成员名1>=<成员值1>,<成员名2>=<成员值2>,..)
package grammar;
@Description(desc="I am" ,author="liu",age=22)
public class UseAnnotation {
public String Test() {
return "red";
}
}
- **解析注解 **
概念: 通过反射获取类、函数或成员上的运行时注解信息,从而实现动态控制程序运行的逻辑。注意,解析注解时, @Retention(RetentionPolicy.RUNTIME) 是必须的。
1. 先获取类对象
2. 类对象调用 isAnnotationPresent(Class<? extends Annotation> annotationClass)判断是否应用了某个注解
3. 通过 getAnnotation() 方法来获取 Annotation 对象,或者getAnnotations() 方法获取所有应用在该类上的注解
示例:
注解类:
package grammar;
@Target({ElementType.METHOD , ElementType.TYPE})
@Retention( RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface DesSimple {
String value();
}
应用注解类:
package grammar;
@DesSimple("this is a type ano")
public class Child {
@DesSimple("this is a method ano")
public String name() {
return "name";
}
}
解析注解类:
package grammar;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
public class ParseAnnotation {
public static void main(String[] args) {
try {
//1.使用类加载器加载类对象
Class clazz = Class.forName("grammar.Child");
//2. 判断是否应用了这个注解
boolean hasAnno = clazz.isAnnotationPresent(DesSimple.class);
//3. 获取Annotation对象
if(hasAnno) {
DesSimple ds = (DesSimple)clazz.getAnnotation(DesSimple.class);
System.out.println(ds.value());
}
//4. 找到方法上的注解
Method[] ms = clazz.getMethods();
/******** 第一种解析方式 ************/
for(Method m:ms) {
boolean isMExist = m.isAnnotationPresent(DesSimple.class);
if(isMExist ) {
DesSimple dsm = (DesSimple)m.getAnnotation(DesSimple.class);
System.out.println(dsm.value());
}
}
/************ 另一种解析方式 ******************/
for(Method m: ms) {
Annotation[] ans = m.getAnnotations();//获取所有注解在该方法上的注解
for(Annotation an:ans) {
if(an instanceof DesSimple) {
DesSimple desSimple = (DesSimple)an;
System.out.println(desSimple.value());
}
}
}
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}