概念
说明程序的,给程序员看的。
功能
-
编写文档∶通过代码里标识的注解生成文档【生成文档doc文档】
-
代码分析∶通过代码里标识的注解对代码进行分析【使用反射】
-
编译检查:通过代码里标识的注解让编译器能够实现基本的编译检查【override]
JDK中预定义的一些注解
- @Override :检测被该注解标注的方法是否是继承自父类(接口)的
- @Deprecated:该注解标注的内容,表示已过时
- @suppresswarnings:压制警告
样例
package annotation;
@SuppressWarnings("all")
// 压制警告需要带一个参数。一般都选all。压制所有警告
// 一旦添加了这个注解,所包含的区域。警告都不会报。例如:改变量、方法未使用警告
public class PredefineTest {
int age;
String name;
@Override
// 继承object类。重写tostring方法。
public String toString() {
// TODO Auto-generated method stub
return super.toString();
}
@Deprecated
// 已过时的方法。如果添加这个注解。在方法上面会有一条横线划过
public void show1() {
System.out.println("该方法已经过时了~~~");
}
public void show2() {
System.out.println("该方法没有过时哟");
}
}
自定义注解
格式
- 元注解
- public @interface 注解名称{ 方法体 }
本质
注解本质上就是一个接口,该接口默认继承Annotation接口。如下所示:
public interface 注解名称 extends java. lang . annotation. Annotation { 方法体 }
属性:接口中的抽象方法
方法体注意事项
接口中的抽象方法对于返回值类型是有要求的,有且仅有这几种,其他的都不行,如下所示:
- 基本数据类型
- String数据类型
- 枚举类型
- 注解类型
- 以上类型的数组
样例:
package annotation;
public @interface Test1{
// 基本数据类型
public abstract int f1();
// String数据类型
public abstract String f2();
// 枚举类型
public abstract ColorEnumTest f3();
// 注解类型
public abstract Test2 f4();
// 以上,数据数组类型
public abstract String[] f5();
}
赋值方法体
根据自定义注解,方法体有什么抽象方法,那么使用注解的时候。一定要给他赋值。就用上面那个样例来说。如果要使用该注解。必须书写:@Test1(f1 = 1,f2 = "abc",f3 = ColorEnumTest.GREEN,f4 = @Test2,f5 = {"abc","edf","hij"})
也相当于,各种返回值类型的使用方法。如果不想,在使用注解的时候定义。那么可以在注解类中,加上 default 对应返回值类型的数据
。如:public abstract int f1() default 12;
元注解
概念:
用于描述注解的注解
包含:
-
@Target :描述注解能够作用的位置
参数:- ElementType
取值:- TYPE:可以作用于类上
- METHOD:可以作用于方法上
- FIELD:可以作用于成员变量上
- ElementType
-
@Retention :描述注解被保留的阶段
参数:- RetentionPolicy
取值:- SOURCE:class第一个阶段。源代码阶段
- CLASS:class第二个阶段。类加载器阶段
- RUNTIME:class第三个阶段。运行时阶段
(一般选择这个阶段)
- RetentionPolicy
-
@Documented :描述注解是否被抽取到api文档中
-
@Inherited :描述注解是否被子类继承
样例:
package annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(value = ElementType.TYPE)
@Retention(value = RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface Test1{
// 基本数据类型
public abstract int f1() default 12;
// String数据类型
public abstract String f2();
// 枚举类型
public abstract ColorEnumTest f3();
// 注解类型
public abstract Test2 f4();
// 以上,数据数组类型
public abstract String[] f5();
}
使用注解—结合反射技术
步骤:
- 获取使用该注解的字节码文件
- 通过字节码文件可以获取注解
- 获取注解的内容
- 运用反射技术。实例化一个对象出来
- 获取抽象方法
- 执行抽象方法
样例:
package annotation;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
@Test2(classname = "annotation.Teacher" , methodname = "work")
public class Main {
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
// 1. 获取Main.class字节码
Class<Main> mainClass = Main.class;
// 2. 获取他的注解
Test2 an = mainClass.getAnnotation(Test2.class);
// 3. 获取注解的内容
String className = an.classname();
String methodName = an.methodname();
// 4. 运用反射技术.加载该类进入内存
Class cls = Class.forName(className);
// 5. 创建这样一个对象
// 如果想创建有参构造函数。参数使用,基本数据类型.class
Constructor con = cls.getDeclaredConstructor();
// 如果有参。写真实数据
Object obj = con.newInstance();
// 6. 获取抽象方法
Method method = cls.getDeclaredMethod(methodName);
method.setAccessible(true); // 暴力反射
// 7. 执行抽象方法
method.invoke(obj);
}
}