Java Annotation

1.注解是什么

注解(Annotation)也叫元数据,是JDK5.0引入的一种注释机制,用于对代码进行配置说明,可以对包,类,接口,字段,方法参数,局部变量等进行使用。

一般注解可以划分为以下三类:

  • 元注解: 元注解使用与定义注解的注解,包含@Retention(标明注解被保留的阶段),@Target(标明注解使用的范围),@Inherit额的(标明注解可继承),@Documented(标明是否生成javadoc文档)
  • java自带的标注注解:包含开发人员常见的@OverRide(标明重写某个方法),@Deprecated(标明某个类或方法已经过时),@SuppressWarning(标明要忽略的警告),使用这些注解这些注解后编译器就会进行检查
  • 自定义注解:按照注解的需求结合元注解定义新注解

2.注解的作用

在介绍注解(Annotation)的作用之前我们先介绍下xml,在注解引入之前,xml被广泛的应用于描述元数据,然而随着代码的增加,并且由于xml并没有和代码紧密的耦合在一起,xml的维护变得越来越复杂,此时注解(Annotation)被创造出来,通过使用注解,代码和元数据配置紧密的耦合在了一起,代码维护被简化

3.注解的原理

(01) @interface

使用 @interface 定义注解时,意味着它实现了 java.lang.annotation.Annotation 接口,即该注解就是一个Annotation。

定义 Annotation 时,@interface 是必须的。

注意:它和我们通常的 implemented 实现接口的方法不同。Annotation 接口的实现细节都由编译器完成。通过 @interface 定义注解后,该注解不能继承其他的注解或接口。

(02) @Documented

类和方法的 Annotation 在缺省情况下是不出现在 javadoc 中的。如果使用 @Documented 修饰该 Annotation,则表示它可以出现在 javadoc 中。

定义 Annotation 时,@Documented 可有可无;若没有定义,则 Annotation 不会出现在 javadoc 中。

(03) @Target(ElementType.TYPE)

前面我们说过,ElementType 是 Annotation 的类型属性。而 @Target 的作用,就是来指定 Annotation 的类型属性。

@Target(ElementType.TYPE) 的意思就是指定该 Annotation 的类型是 ElementType.TYPE。这就意味着,MyAnnotation1 是来修饰"类、接口(包括注释类型)或枚举声明"的注解。

定义 Annotation 时,@Target 可有可无。若有 @Target,则该 Annotation 只能用于它所指定的地方;若没有 @Target,则该 Annotation 可以用于任何地方。

(04) @Retention(RetentionPolicy.RUNTIME)

前面我们说过,RetentionPolicy 是 Annotation 的策略属性,而 @Retention 的作用,就是指定 Annotation 的策略属性。

@Retention(RetentionPolicy.RUNTIME) 的意思就是指定该 Annotation 的策略是 RetentionPolicy.RUNTIME。这就意味着,编译器会将该 Annotation 信息保留在 .class 文件中,并且能被虚拟机读取。

定义 Annotation 时,@Retention 可有可无。若没有 @Retention,则默认是 RetentionPolicy.CLASS。

4.注解的使用

package com.annotation.test;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE) //Type表示该注解作用于普通类,接口类,或枚举
@Retention(RetentionPolicy.RUNTIME) //注解会被编译器记录在类文件中,在运行时由虚拟机保留,因此可以通过反射读取到它们
public @interface MyClassAnnotation { //自定义作用于类的注解
    
    String value() default "";
    
    String[] classAnnoFunc() default {};

}
package com.annotation.test;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.FIELD) //Feild 表示作用于字段声明(包括枚举常量)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyFieldAnnotation {
    
    String value() default "";
    
    String[] fieldAnnoFunc() default {};

}
package com.annotation.test;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD) //@Target可有可无,如果没有添加Target则表示该注解可以使用在任何地方
@Retention(RetentionPolicy.RUNTIME)//@Retention可有可无,如果没有则默认为Retentionpolicy.CLASS
public @interface MyMethodAnnotation {
    
    String value() default "";
    
    String[] methodAnnoFunc() default {};
    
}
package com.annotation.test;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.PARAMETER) //参数声明
@Retention(RetentionPolicy.RUNTIME)
public @interface MyParamAnnotation {
    
    String value() default "";

}
package com.annotation.test;

@MyClassAnnotation(value = "classValue", classAnnoFunc = "")
public class MyAnnotationTest {
    
    @MyFieldAnnotation
    public String testField;
    
    @MyMethodAnnotation(methodAnnoFunc = "testAnnotation")
    public String testFunction(@MyParamAnnotation("paramValue")String param) {
        return param;
    }

}
package com.annotation.test;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;

public class MainTest {

    public static void main(String[] args) throws ClassNotFoundException {
        
        //通过字节码获取对象
        Class<?> aClass = MyAnnotationTest.class;
        //通过Class.forName 获取对象
        Class<?> bClass = Class.forName("com.annotation.test.MyAnnotationTest");
        //通过getClass获取对象
        Class<?> cClass = new MyAnnotationTest().getClass();
        
        //查看该类是否存在自定义的注解
        boolean classFlag = bClass.isAnnotationPresent(MyClassAnnotation.class);
        if(classFlag) {
            Annotation[] annotations = bClass.getAnnotations();
            for(Annotation anno : annotations) {
                System.out.println(aClass.getName() + " --- " + ((MyClassAnnotation) anno).value() );
                System.out.println(aClass.getName() + " --- " + ((MyClassAnnotation) anno).classAnnoFunc() );
            }
        }
        
        System.out.println("---------------");
        
        
        //通过反射获取该对象的所有方法
        Method[] methods = bClass.getMethods();
        for(Method m : methods) {
           //遍历方法里面是否存在该自定义的注解
           boolean methodFlag = m.isAnnotationPresent(MyMethodAnnotation.class);
         //分析注解里面的参数
           if(methodFlag) {
               MyMethodAnnotation methodAnnotation = m.getAnnotation(MyMethodAnnotation.class);
               System.out.println(m.getName() + " : " + methodAnnotation);
               
           }else {
               System.out.println(m.getName() + " 该方法未曾使用到注解");
           }
           
           //通过反射获取该方法的所有参数
           Parameter[] parameters = m.getParameters();
           for(Parameter param : parameters) {
               boolean paramFlag = param.isAnnotationPresent(MyParamAnnotation.class);
               if(paramFlag) {
                   MyParamAnnotation annotation = param.getAnnotation(MyParamAnnotation.class);
                   System.out.println(m.getName() + " : --- " + annotation.value());
               }
           }
       }
       
        System.out.println("---------------");
       
       //通过反射获取对象的所有属性
       Field[] fields = bClass.getFields();
       for(Field f : fields) {
           //查看属性上面是否存在改自定义的注解
           boolean fieldFlag = f.isAnnotationPresent(MyFieldAnnotation.class);
           //分析注解里面的参数
           if(fieldFlag) {
               MyFieldAnnotation fieldAnnotation = f.getAnnotation(MyFieldAnnotation.class);
               System.out.println(f.getName() + " : " + fieldAnnotation);
           }else {
               System.out.println(f.getName() + " : " + "该属性未曾使用到注解");
           }
       }
    }

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值