注解的属性类型
注解只能存放简单的数据
如:
基本数据类型
String
Class
注解
枚举
以上类型的一维数组
格式:
public @interface 注解名称 {
public 属性类型 属性名();
}
public @interface MyAn1 {
public String name();//String类型
int age();//基本数据类型
Class aaa();//Class类型
Enum1 bbb();//枚举类型
//注解类型
MyAn2 ddd();
//以上类型的一维数组
//不能用自定义类型
String[] ccc();
String value();//名字为value时,在用注解时可以省略
}
public @interface MyAn2 {//空注解
}
public @interface MyAn3 {
String name();
int age();
}
@MyAn3(name = "李四",age = 99)
public class Demo {
public static void main(String[] args) {
}
}
元注解
什么是元注解?
修饰注解的注解
元注解@Target
正常情况注解可以放在类的任何一个元素上面
作用:
用来标识注解使用的位置,如果没有使用该注解标识,则自定义的注解可以使用在任意位置。
可使用的值定义在ElementType枚举类中,常用值如下
TYPE,类,接口
FIELD, 成员变量
METHOD, 成员方法
PARAMETER, 方法参数
CONSTRUCTOR, 构造方法
LOCAL_VARIABLE, 局部变量
元注解@Retention
作用:
用来标识注解的生命周期(有效范围)
可使用的值定义在RetentionPolicy枚举类中,常用值如下
默认是CLASS
SOURCE:注解只作用在源码阶段,生成的字节码文件中不存在
CLASS:注解作用在源码阶段,字节码文件阶段,运行阶段不存在,默认值
RUNTIME:注解作用在源码阶段,字节码文件阶段,运行阶段
注解解析
注解解析就是得到注解中的数据
AnnotatedElement接口
Annotation[] getAnnotations() 获取所有注解
< Annotation > T getAnnotation(Class< T > annotationClass) 获取一个指定的注解
boolean isAnnotationPresent(Class< Annotation > annotationClass) 判断是否有指定的注解
如何解析注解?
通过反射来解析注解,原则注解在谁头上就用谁来解析
如果注解在构造方法上,使用Constructor来获取
如果注解在成员方法上,使用Method来获取
如果注解在成员变量上,使用Field来获取
定义这样一个注解,必须是RUNTIME时期,因为getAnnotations只能拿到RUNTIME时期的注解
@Retention(RetentionPolicy.RUNTIME)
public @interface StudentAnno {
String name();
int age();
String[] parent();
}
将注解用于此类方法
public class Student {
@StudentAnno(name = "elephant",age = 11,parent = {"dog", "cat"})
public void study(){
System.out.println("认真学习");
}
}
解析注解
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
Class<Student> cls = Student.class;
Method study = cls.getMethod("study");
boolean b = study.isAnnotationPresent(StudentAnno.class);
if (b) {
StudentAnno annotation = study.getAnnotation(StudentAnno.class);
System.out.println("我的名字是" + annotation.name() + "\r\n" + "今年" + annotation.age() + "岁\r\n" + "父母是" + Arrays.toString(annotation.parent()));
}
}
模拟junit
首先创建一个注解
@Retention(RetentionPolicy.RUNTIME)
public @interface MyTest {
}
接着在方法上添加注解
public class Teacher {
/*
所以junit里面的方法是public 无返回值 ,无参数
方便反射
*/
public void study(){
System.out.println("学习");
}
@MyTest
public void eat(){
System.out.println("吃饭");
}
@MyTest
public void sleep(){
System.out.println("睡觉");
}
}
最后解析注解,如果有此注解则运行方法
public static void main(String[] args) throws Exception {
Class<Teacher> cls = Teacher.class;
Method[] methods = cls.getMethods();
Teacher teacher = cls.getConstructor().newInstance();
for(Method m : methods){
boolean b = m.isAnnotationPresent(MyTest.class);
if(b){
m.invoke(teacher);
}
}
}
最后
如果你对本文有疑问,你可以在文章下方对我留言,敬请指正,对于每个留言我都会认真查看。