注解作用
- 编译检查
- 文档生成,javadoc
- 代码分析,使用反射对代码的注释进行分析
jdk预定义注解
@Override注解
用于重写父类的方法 或者是写接口实现类时用到该注解。
@Deprecated注解
用于表示该方法是一个过期的方法。
@suppressWarnings注解
表示该方法在编译时自动忽略警告。
public class Test {
@Override
public String toString() {
return super.toString();
}
@Deprecated
public void test1()
{
//弃用
}
@SuppressWarnings("all")
public void test2()
{
//压制所有警告
}
}
自定义注解
本质是一个接口,继承自java。lang。annotation.Annotation
格式
//public interface Yungang extends java.lang.annotation.Annotation {}
public @interface Yungang {
}
属性
接口中的抽象方法
属性的返回值只能是以下取值:
- 基本类型
- String
- 枚举
- 注解
- 以上类型的数组
特点:
1.定义了属性后,需要给属性赋值,或者在注解中使用default
2.只有一个属性时,并且属性名称为value,则可以省略名称
元注解
@Target
描述注解能够作用的位置
ElementType的取值:
- TYPE:类
- METHOD: 方法
- FIELD:成员变量
@Retention
描述注解被保留的阶段
- RetentionPolicy.RUNTIME : 当前被描述的注解,会保留到class字节码文件中,并被JVM读取到
@Document
描述注解是否被抽取到api文档中
@Inherited
描述注解会被子类继承
@Target(value = {ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface Yungang {
String test1();
double test2();
}
测试
@Yungang(test1 = "test", test2 = 3.0)
public class Test {
@Override
public String toString() {
return super.toString();
}
@Deprecated
public void test1()
{
//弃用
}
@SuppressWarnings("all")
public void test2()
{
//压制所有警告
}
@Yungang(test1 = "test2", test2 = 1.0)
public void test3(){
}
}
解析注解
获取注解中定义的属性值,可用于配置文件
获取注解定义的位置(类、函数、属性 )的对象
获取指定注解,getAnnotation(class)
例子
定义注解类
import java.lang.annotation.*;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ClassInfo {
String classname();
String methodname();
}
使用注解,获取注解值
@ClassInfo(classname = "com.reflect.Person", methodname = "show")
public class TestReflect {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//获取当前类字节码
Class<TestReflect> testReflectClass = TestReflect.class;
//通过字节码获取当前类的注解对象
// 这里的 annotation 是实现了ClassInfo接口的子类,故可以调用方法获取返回值(返回定义的值)
ClassInfo annotation = testReflectClass.getAnnotation(ClassInfo.class);
// 使用反射拿到配置中类和方法
Class aClass = Class.forName(annotation.classname());
Constructor constructor = aClass.getConstructor();
Person person = (Person) constructor.newInstance();
person.function("xyg");
}
}
Person类
ublic class Person {
public Person() {
}
public void show() {
System.out.println("show");
}
public void function(String s) {
System.out.println("function:" + s);
}
}
自定义测试类
注解类
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface JunitDemo {
}
要测试的方法上添加自定义注解
public class Calculator {
@JunitDemo
public void test1(){
System.out.println(1 / 2);
}
@JunitDemo
public void test2(){
System.out.println("true = " + true);
}
@JunitDemo
public void test3(){
System.out.println(2 / 0); // 此方法有异常,使用测试类找出
}
}
使用注解,找到有异常的方法
Calculator calculator = new Calculator(); // 获取测试类
Class aClass = calculator.getClass(); // 获取字节码
Method[] methods = aClass.getMethods(); // 获取测试类所有方法
for (Method method: methods
) {
// 遍历所有方法,找到存在JunitDemo注解的方法
if (method.isAnnotationPresent(JunitDemo.class))
{
try {
// 执行方法,并捕获异常
method.invoke(calculator);
}catch (Exception e) {
// 打印方法名并输出异常类型
System.out.println("method: " +method.getName() + " have exception , type is "+ e);
}
}
}
}