1.概念
注解表示一个标识(标注、标记),它可以用在类上、方法上、变量上等,给类的各个组成部分一些额外的表示,能够被编译器识别。
2.常见注解
@Override: 描述一个方法是复写的父类方法
@Deprecate: 描述一个方法是过时的方法,调用过时的方法会有一个横线
@SuppressWarnings(value = “all”): 压制警告:写在类上,则压制整个类的警告,在方法上则压制方法上的警告
3.自定义注解
【在使用注解的时候如果注解里面的属性没有指定默认值,那么我们就需要手动给出注解属性的设置值。】
public @interface Anno {
//定义一个基本类型的属性
//public属性类型属性名() default 默认值;
int a() default 23 "张三";
//定义一个String类型的属性
public String name() default 23;
//定义一个class类型的属性
public Class clazz() default Anno2.class;
//定义一个注解类型的属性
public Anno2 anno() default @Anno2;
//定义一个枚举类型的属性
public Week week() default Week.Monday;
//以上类型的一维数组
//int 数组
public int [] arr() default {1,2,3,4,5}
//枚举数组
public Week[] weeks() default{Week.Monday}
public String value();
//特殊属性value 变量只有一个,则使用时可以省略名称直接赋值
}
//类上使用注解
//在使用注解的时候如果注解里面的属性没有指定默认值,那么我们就需要手动给出注解属性的设置值。
//此处相当于Anno的对象,只是给类或者方法添加了一个标签,不会影响实体
@Anno("李四")
public class Demo1 {
public static void main(String[] args) {
}
}
4.元注解
@Target:指定了注解能在哪里使用【成员变量、类、方法】
@Retention:可以理解为保留时间(生命周期)
@lnherited:表示修饰的自定义注解可以被子类继承
@Documented:表示该自定义注解,会出现在API文档里面
//定义特殊属性value
@Retention(RetentionPolicy.RUNTIME) //注解在运行时期有效
@Target(ElementType.TYPE)//注解可以使用在类上
//@Target(ElementType.METHOD)//注解可以使用在方法上
//@Target(ElementType.FIELD)//注解可以使用在成员变量上
@Inherited//表示修饰的自定义注解可以被子类继承
public @interface Anno {
}
//测试类
public class Demo2 {
public static void main(String[] args) throws ClassNotFoundException {
//得到类的字节码对象
Class<?> personClazz = Class.forName("com.itheima3.Person");
//getAnnotation(Anno.class);得到该类的注解对象
Anno a1 = personClazz.getAnnotation(Anno.class);
Class<?> studentClazz = Class.forName("com.itheima3.Student");
Anno a2 = personClazz.getAnnotation(Anno.class);
System.out.println(a1==a2);
}
}
打印结果
true
5.自定义注解实现
测试让有注解的方法执行,没有Test的方法不执行
//自定义注解
//元注解[对注解进一步进行说明]
@Target(ElementType.METHOD)//指定注解可以用在哪些地方
@Retention(RetentionPolicy.RUNTIME)//表示注解的存活时间可以到运行
//定义一个注解
public @interface Test {
}
//方法类
public class UseTest {
//没有使用Test注解
public void show(){
System.out.println("UseTest....show....");
}
//使用Test注解
@Test
public void method(){
System.out.println("UseTest....method....");
}
//使用Test注解
@Test
public void function(){
System.out.println("UseTest....function....");
}
}
//测试类
//测试让有注解的方法执行,没有Test的方法不执行
public class AnnoDemo {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//通过反射获取UseTest的字节码文件对象
Class<?> clazz = Class.forName("com.itheima2.UseTest");
//2.通过反射获取这个类里面所有方法的对象
Method[] methods = clazz.getDeclaredMethods();
//创建对象用于执行方法
Object o = clazz.getConstructor().newInstance();
//遍历数组,得到每一个方法对象
for (Method method : methods) {
//getAnnotation(Test.class)返回原方法上额外的注解
Test test = method.getAnnotation(Test.class);
//如果有注解,就执行
if (test != null) {
//注解没有设置存活时间,则打印无结果
method.invoke(o);
}
//method.isAnnotationPresent(Test.class)判断方法上是否有注解,有则返回true
/*if(method.isAnnotationPresent(Test.class)){
method.invoke(o);
}*/
}
}
}
打印结果:
-------------------------------------------------------------------------------
UseTest....method....
UseTest....function....