自定义注解

1. annotation(注解)含义

  • 注解本质是一个继承了Annotation的特殊接口,其具体实现类是Java运行时生成的动态代理类。而我们通过反射获取注解时,返回的是Java运行时生成的动态代理对象$Proxy1。通过代理对象调用自定义注解(接口)的方法,会最终调用AnnotationInvocationHandler的invoke方法。该方法会从memberValues这个Map中索引出对应的值。而memberValues的来源是Java常量池。
  • annotation是Java提供的一种元程序中的元素关联任何信息和任何元数据(metadata)的途径和方法。
  • annotation是一个接口,程序可以通过反射来获取指定程序元素的annotation对象,然后通过annotation对象来获取注解里面的元数据。
  • annotation就像修饰符一样被使用,并应用于包、类型、构造方法、方法、成员变量、参数、本地变量的声明中。这些信息被存储在annotation的“name=value”结构对中。
2. 自定义注解

  • 使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口,由编译程序自动完成其他细节。在定义注解时,不能继承其他的注解或接口。
  • @interface用来声明一个注解,其中的每一个方法实际上是声明了一个配置参数。
  • 方法的名称就是参数的名称,返回值类型就是参数的类型(返回值类型只能是基本类型、Class、String、enum)。可以通过default来声明参数的默认值。
2.1 自定义注解格式:
/**
 * 自定义注解 
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface 注解名 {
    注解体
}
2.2 参数设置:
  • 只能用public或default这两个访问权修饰.例如,String value();这里把方法设为defaul默认类型;
  • 参数成员只能用基本类型(byte,short,char,int,long,float,double,boolean八种基本数据类型和String,Enum,Class,annotations等数据类型,以及这一些类型的数组.例如,Stringvalue();这里的参数成员就为String;
  • 如果只有一个参数成员,最好把参数名称设为"value",后加小括号。 例如:
/**
 * xxx注解
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface xxx {
    String value() default "";
}
2.3 注解元素的默认值
  • 注解元素必须有确定的值,要么在定义注解的默认值中指定,要么在使用注解时指定,非基本类型的注解元素的值不可为null。
  • 因此,使用空字符串或0作为默认值是一种常用的做法。
2.4 注解处理器类库(java.lang.reflect.AnnotatedElement)

(1)注解元素使用Annotation接口来代表程序元素前面的注解,该接口是所有Annotation类型的父接口。

(2)除此之外,Java在java.lang.reflect 包下新增了AnnotatedElement接口,该接口代表程序中可以接受注解的程序元素,该接口主要有如下几个实现类:

  • Class:类定义
  • Constructor:构造器定义
  • Field:类的成员变量定义
  • Method:类的方法定义
  • Package:类的包定义
2.5 访问annotation的信息
  • 方法1:<T extends Annotation> T getAnnotation(Class<T>annotationClass) 返回该程序元素上存在的、指定类型的注解,如果该类型注解不存在,则返回null;
  • 方法2:Annotation[] getAnnotations() 返回该程序元素上存在的所有注解;
  • 方法3:boolean isAnnotationPresent(Class<?extends Annotation> annotationClass) 判断该程序元素上是否包含指定类型的注解,存在则返回true,否则返回false;
  • 方法4:Annotation[] getDeclaredAnnotations() 返回直接存在于此元素上的所有注释。与此接口中的其他方法不同,该方法将忽略继承的注释。(如果没有注释直接存在于此元素上,则返回长度为零的一个数组。)该方法的调用者可以随意修改返回的数组;这不会对其他调用者返回的数组产生任何影响。
3. 示例

自定义xxx注解–>编写注解解析器–>在某个类中使用注解–>注解测试

/**
* 自定义球颜色注解
*/
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface BallColor {

    public enum MyColor {
        YELLOW,BLUE,GREEN,BLACK,RED,PINK
    }
    
    public MyColor ballColor() default MyColor.BLUE;
}
/**
* 自定义球类别注解
*/
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface BallType {

    String value() default "ball";
    
}
/**
* 注解解析器
*/
public class BallParser {
    
    public static void getBallInfo(Class<?> clazz){
        
        String strBallColor = "球颜色:";
        String strBallType = "球类别:";
        
        //得到所有方法包括私有方法,返回一个数组
        Field[] fields = clazz.getDeclaredFields();
        
        for (Field field:fields) {
            //判断该程序元素上是否包含指定类型的注解
            if (field.isAnnotationPresent(BallColor.class)) {
                BallColor ballColor = (BallColor)field.getAnnotation(BallColor.class);
                strBallColor = strBallColor + ballColor.ballColor().toString();
                System.out.println(strBallColor);
            }
            if (field.isAnnotationPresent(BallType.class)) {
                BallType ballType = (BallType)field.getAnnotation(BallType.class);
                strBallType = strBallType + ballType.value();
                System.out.println(strBallType);
            }
        }
/**
* 在类中使用注解
*/
public class Ball {

    @BallType
    private String ballType;
    
    @BallColor(ballColor=MyColor.GREEN)
    private String ballColor;

    public String getBallType() {
        return ballType;
    }

    public void setBallType(String ballType) {
        this.ballType = ballType;
    }

    public String getBallColor() {
        return ballColor;
    }

    public void setBallColor(String ballColor) {
        this.ballColor = ballColor;
    }
    
}
/**
* 注解测试
*/
public class BallTest {
    
    public static void main(String[] args){
        
        BallParser.getBallInfo(Ball.class);
    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值