定义:
注解(Annotation),也叫元数据。一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。
作用:
1、编写文档:通过代码里标识的注解生成文档【生成文档doc文档】
2、代码分析:通过代码里标识的注解对代码进行分析【使用反射】
3、编译检查:通过代码里标识的注解让编译器能够实现基本的编译检查【Override】
注解和注释的区别:
JDK中预定义的一些注解:
- @Override :检测被该注解标注的方法是否是继承自父类(接口)的
- @Deprecated:该注解标注的内容,表示已过时
- @SuppressWarnings:压制警告
- 一般传递参数all @SuppressWarnings(“all”)
自定义注解:
**格式:**
//元注解列表
public @interface 注解名称{
//属性列表
public 属性类型 属性名() default 默认值 ; //public可以省略
}
注解的本质就是一个接口,该接口默认继承Annotation 接口,
public interface MyAnno extends java.lang.annotation.Annotation {}
注解的属性列表:可以等同理解为接口中的抽象方法。
1、属性返回值类型的取值
2、定义了属性,在使用时需要给属性赋值
3、元注解:就是用来描述注解的注解
//自定义注解代码案例
@Retention(RetentionPolicy.RUNTIME)
@Target(value = ElementType.TYPE)
public @interface Anno1 {
//定义一个基本类型的属性
int a () default 23;
//定义一个String类型的属性
public String name() default "itheima";
//定义一个Class类型的属性
public Class clazz() default Anno2.class;
//定义一个注解类型的属性
public Anno2 anno() default @Anno2;
//定义一个枚举类型的属性
public Season season() default Season.SPRING;
//以上类型的一维数组
//int数组
public int[] arr() default {1,2,3,4,5};
//枚举数组
public Season[] seasons() default {Season.SPRING,Season.SUMMER};
//value。后期我们在使用注解的时候,如果我们只需要给注解的value属性赋值。那么value就可以省略
public String value();
}
//在使用注解的时候如果注解里面的属性没有指定默认值。那么我们就需要手动给出注解属性的设置值。
//@Anno1(name = "study")
@Anno1("abc") //该注解作用在类上
public class AnnoDemo {
//...
}
4、程序使用注解的过程
- 获取注解定义的位置的对象 (Class,Method,Field)
- 获取指定的注解 getAnnotation(Class),其实就是在内存中生成了一个该注解接口的子类实现对象
- 调用注解中的抽象方法获取配置的属性值
案例:
自定义注解,使用注解,并通过Java反射机制获取注解中的参数值
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 自定义注解
*/
@Retention(RetentionPolicy.RUNTIME) //保留时间或生命周期
@Target(value = ElementType.METHOD) //作用在方法上
public @interface Execute {
String value() default "this is an annotation.";
String[] paramData() default {"1","2"};
}
import lombok.Data;
/**
* 使用注解
*/
@Data
public class AnnotationDemo {
public void demo1(){
System.out.println("demo1 : 没有加注解 执行了。。。");
}
@Execute(value = "我是注解的默认值")
public void demo2(){
System.out.println("demo2 加了注解 执行了。。。");
}
public void demo3(){
System.out.println("demo3 没有注解 执行了。。。");
}
}
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* 通过反射获取注解并获取其中的属性值
*/
public class AnnoTest {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException {
//通过反射获取UseTest类的字节码文件对象
Class<?> aClass = Class.forName("com.awe.hrm.anno.AnnotationDemo");
//通过Class对象创建当前类对象
AnnotationDemo o = (AnnotationDemo) aClass.newInstance();
//获取这个类里面所有的方法对象
Method[] declaredMethods = aClass.getDeclaredMethods();
//遍历方法对象数组
for (Method declaredMethod : declaredMethods) {
//判断当前方法对象中是否包含(Execute)注解
if (declaredMethod.isAnnotationPresent(Execute.class)) {
//执行当前有注解方法
declaredMethod.invoke(o);
//获取当前方法上注解的 (value)属性的值并打印
String value = declaredMethod.getAnnotation(Execute.class).value();
System.out.println(value);
//获取当前方法上注解的 (paramData)属性的值并遍历打印
String[] strings = declaredMethod.getAnnotation(Execute.class).paramData();
for (String string : strings) {
System.out.println(string + ",");
}
}
}
}
}
main方法执行打印结果:
小结:
- 注解不是程序的一部分,可以理解为注解就是一个标签