文章目录
- 注解
- 注解的作用
- 注解的语法
- 注解的使用
- 元注解
- 注解处理器
- 案例
- 注解VS配置文件
- 注解的应用
注解
- Annotation是代码里的特殊标记,这些标记可以在编译、类加载、运行时被读取,并执行相应的处理
- 可以把Annotation理解为一个标签
- 注解是不允许继承的
注解的作用
- 通过使用Annotation,程序开发人员可以在不改变原有逻辑的情况下,在源文件嵌入一些补充信息
- Annotation就像修饰符一样被使用,可用于修饰类、构造器、方法、成员变量、参数…,这些信息被存储在Annotation的“属性名=属性值”对中。
注解 VS 注释
- 相同点
- 都是用来传递额外信息的
- 不同点
- 注解可以参与编译,注释不行
- 注解有使用范围,注释没有(想咋写咋写)
- 注解作为一种数据类型,跟class interface具有同等地位
注解的语法
权限修饰符 @interface 注解名字{// 注解体定义属性类型 属性名();属性类型 属性名();属性类型 属性名();......
}属性类型:
基本数据类型
String类型
Class类型
注解类型
枚举类型
以及以上类型的数组形式
eg:
public @interface MyAnnotation {int a1();double a2();String a3();Class a4();MyAnnotation2 a5();String[] str();Season a6();
}@interface MyAnnotation2{}enum Season{SPRING,SUMMER,AUTUMN,WINTER
}
注解的使用
@注解名(属性1=属性值,属性2=属性值)
注意事项:
-
每个属性都要赋值
-
可以不赋值,但是要有默认值, default
-
数组形式赋值
{}
-
如果只有1个属性, 名字叫value, 可以简化赋值
-
如果属性类型是引用类型, 不能是null
eg:
public class Demo {public static void main(String[] args) {}@MyAnno0(hobby = {"football", "basketball", "tennis"})@MyAnno1("zs")public static void func() {}
}@interface MyAnno0 {// 注解体int age() default 0;String name() default "zs";String[] hobby();
}@interface MyAnno1 {// 注解体String value();
}
元注解
- 描述注解的注解(注解的注解)
- 元数据 meta data
常用元注解:
-
@Retention
元注解,来定义我们自己定义的注解的保留级别-
RetentionPolicy.RUNTIME
-
RetentionPolicy.CLASS
默认 -
RetentionPolicy.SOURCE
-
-
@Target
元注解,注解可以作用的目标-
对于注解而言,可以作用的目标:
-
- 整个类
ElementType.TYPE
- 整个类
-
- 成员变量
ElementType.FIELD
- 成员变量
-
- 构造方法
ElementType.CONSTRUCTOR
- 构造方法
-
- 成员方法
ElementType.METHOD
- 成员方法
-
-
eg:
注解处理器
eg:
public class Demo {public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {// 获取字节码文件对象Class<?> c = Class.forName("com.csdn.Demo");// 得到方法对象Method loginMethod = c.getDeclaredMethod("login");// 判断方法上面是否使用注解了boolean annotationPresent = loginMethod.isAnnotationPresent(Login.class);if(annotationPresent){// 获取注解实例Login loginAnnotation = loginMethod.getAnnotation(Login.class);// 获取注解信息String password = loginAnnotation.password();String name = loginAnnotation.name();// 打印System.out.println("password = " + password);System.out.println("name = " + name);}else{System.out.println("未使用注解");}}@Loginpublic static void login(){}
}// 定义注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface Login{// 属性值String name() default "admin";String password() default "admin";
}
案例
定义2个注解 :
-
AgeLimit 属性 maxAge minAge
-
NameLimit 属性 length
定义学生类Student 年龄18-25之间 名字长度不超过5
eg:
StudentFactory自己定义的类:
public class StudentFactory {static Class studentUtils;static {try {studentUtils = Class.forName("com.cskaoyan.Demo0112.Student");} catch (ClassNotFoundException e) {e.printStackTrace();}}// 提供一个获取学生对象的方法public static Student getInstance(String name, int age)throws NoSuchFieldException, NoSuchMethodException,InvocationTargetException,InstantiationException, IllegalAccessException {// 通过字节码文件获取对象// 判断名字judgeName(name);// 判断年龄judgeAge(age);// 获取构造方法Constructor declaredConstructor = studentUtils.getDeclaredConstructor(String.class, int.class);// 破解declaredConstructor.setAccessible(true);// newInstance 创建对象Student student = (Student) declaredConstructor.newInstance(name, age);// 最终返回一个学生对象return student;}private static void judgeAge(int age) throws NoSuchFieldException {// 获取age成员变量对象Field ageField = studentUtils.getDeclaredField("age");// 是否使用注解boolean annotationPresent = ageField.isAnnotationPresent(AgeLimit.class);if (annotationPresent) {// 获取注解实例AgeLimit ageLimit = ageField.getAnnotation(AgeLimit.class);// 拿到注解信息int min = ageLimit.minAge();int max = ageLimit.maxAge();// 是否在范围内if (age < min || age > max) {throw new IllegalArgumentException("age is illegal");}}}private static void judgeName(String name) throws NoSuchFieldException {// 获取name成员变量Field nameField = studentUtils.getDeclaredField("name");// 是否使用注解boolean annotationPresent = nameField.isAnnotationPresent(NameLimit.class);if (annotationPresent) {// 获取注解实例NameLimit namelimit = nameField.getAnnotation(NameLimit.class);// 拿到注解信息int length = namelimit.length();// 是否在范围内if (name.length() > length) {throw new IllegalArgumentException("name is illegal");}}}
}main函数:
public class Demo {public static void main(String[] args)throws NoSuchFieldException, InvocationTargetException,NoSuchMethodException, InstantiationException,IllegalAccessException {StudentFactory.getInstance("zs",18);StudentFactory.getInstance("ww",1);}
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface AgeLimit{int maxAge() default 25;int minAge() default 18;
}@interface NameLimit{int length();
}class Student{@NameLimit(length = 5)String name;@AgeLimitint age;public Student(String name, int age) {this.name = name;this.age = age;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}
}
注解VS配置文件
配置文件
优点:可配置,不用改源码。管理方便
缺点:不直观,开发效率低
注解
优点:直观开发效率高
缺点:硬编码,修改之后需要重新编译运行,难以和代码分开独立管理
注解的应用
SE :
@Test
@Override
(提供一个额外的信息,方法是重写父类中的方法)@Deprecated
(提供一个额外的信息,方法过时了)@FunctionalInterface
EE :
@WebService
框架:
@AutoWired
@Service
@Mapping
@Data
@Parm