• JAVA 注解的几大作用及使用方法详解


    最近一直Jersey,发现里面有大量的注解,以前虽然看了一些,但是资料都感觉写的很复杂,今天希望通过一个例子,用最简单的方法分享一下到底什么是注解。

    一、创建一个注解

    package com.taobao.Test;
    
    import java.lang.annotation.*;
    
    /* 
     * 定义注解 Test 
     * 为方便测试:注解目标为类 方法,属性及构造方法 
     * 注解中含有三个元素 id ,name和 gid; 
     * id 元素 有默认值 0
     */
    @Target({ ElementType.TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.CONSTRUCTOR })
    @Retention(RetentionPolicy.RUNTIME)
    public @interface TestA {
        String name();
    
        int id() default 0;
    
        Class<Long> gid();
    }

    大家看着可能有些不明白,没事儿,第一次都这样,可以回头在慢慢看,这里先简单解释一下:

    • @Target:是声明在哪里使用,聪明的你看E文就明白差不多了吧
    • @Retention:声明什么时候运行。CLASS、RUNTIME和SOURCE这三种,分别表示注解保存在类文件、JVM运行时刻和源代码中。只有当声明为RUNTIME的时候,才能够在运行时刻通过反射API来获取到注解的信息。
    • @interface:用来声明一个注解

    二、创建一个使用注解的类

    package com.taobao.Test;
    
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * 这个类专门用来测试注解使用
     * 
     * @author tmser
     */
    
    @TestA(name = "type", gid = Long.class)
    // 类成员注解
    public class UserAnnotation {
    
        @TestA(name = "param", id = 1, gid = Long.class)
        // 类成员注解
        private Integer age;
    
        @TestA(name = "construct", id = 2, gid = Long.class)
        // 构造方法注解
        public UserAnnotation() {
    
        }
    
        @TestA(name = "public method", id = 3, gid = Long.class)
        // 类方法注解
        public void a() {
            Map<String, String> m = new HashMap<String, String>(0);
        }
    
        @TestA(name = "protected method", id = 4, gid = Long.class)
        // 类方法注解
        protected void b() {
            Map<String, String> m = new HashMap<String, String>(0);
        }
    
        @TestA(name = "private method", id = 5, gid = Long.class)
        // 类方法注解
        private void c() {
            Map<String, String> m = new HashMap<String, String>(0);
        }
    
        public void b(Integer a) {
    
        }
    }

    其实就是往注解里面添加参数。

    三、使用注解

    package com.taobao.Test;
    
    import java.lang.annotation.Annotation;
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Method;
    
    public class ParseAnnotation {
    
        /**
         * 简单打印出UserAnnotation 类中所使用到的类注解 该方法只打印了 Type 类型的注解
         * 
         * @throws ClassNotFoundException
         */
        public static void parseTypeAnnotation() throws ClassNotFoundException {
            Class clazz = Class.forName("com.taobao.Test.UserAnnotation");
    
            Annotation[] annotations = clazz.getAnnotations();
            for (Annotation annotation : annotations) {
                TestA testA = (TestA) annotation;
                System.out.println("id= "" + testA.id() + ""; name= "" + testA.name() + ""; gid = " + testA.gid());
            }
    //输出 id= "0"; name= "type"; gid = class java.lang.Long }
    /** * 简单打印出UserAnnotation 类中所使用到的方法注解 该方法只打印了 Method 类型的注解 * * @throws ClassNotFoundException */ public static void parseMethodAnnotation() { Method[] methods = UserAnnotation.class.getDeclaredMethods(); for (Method method : methods) { /* * 判断方法中是否有指定注解类型的注解 */ boolean hasAnnotation = method.isAnnotationPresent(TestA.class); if (hasAnnotation) { /* * 根据注解类型返回方法的指定类型注解 */ TestA annotation = method.getAnnotation(TestA.class); System.out.println("method = " + method.getName() + " ; id = " + annotation.id() + " ; description = " + annotation.name() + "; gid= " + annotation.gid()); } } } /** * 简单打印出UserAnnotation 类中所使用到的方法注解 该方法只打印了 Method 类型的注解 * * @throws ClassNotFoundException */ public static void parseConstructAnnotation() { Constructor[] constructors = UserAnnotation.class.getConstructors(); for (Constructor constructor : constructors) { /* * 判断构造方法中是否有指定注解类型的注解 */ boolean hasAnnotation = constructor.isAnnotationPresent(TestA.class); if (hasAnnotation) { /* * 根据注解类型返回方法的指定类型注解 */ TestA annotation = (TestA) constructor.getAnnotation(TestA.class); System.out.println("constructor = " + constructor.getName() + " ; id = " + annotation.id() + " ; description = " + annotation.name() + "; gid= " + annotation.gid()); } } } public static void main(String[] args) throws ClassNotFoundException { parseTypeAnnotation(); parseMethodAnnotation(); parseConstructAnnotation(); } }

    运行输出:

    id= "0"; name= "type"; gid = class java.lang.Long
    method = c ; id = 5 ; description = private method; gid= class java.lang.Long
    method = a ; id = 3 ; description = public method; gid= class java.lang.Long
    method = b ; id = 4 ; description = protected method; gid= class java.lang.Long
    constructor = com.taobao.Test.UserAnnotation ; id = 2 ; description = construct; gid= class java.lang.Long

    如果你还有疑问,想要知道为什么调用诸如:clazz.getAnnotations(); 就返回接口类型的数据,那么可以参考如下内容:

    四、AnnotatedElement接口

    JDK源代码如下:

    public interface AnnotatedElement {
            boolean isAnnotationPresent(Class<? extends Annotation> annotationClass);
            <T extends Annotation> T getAnnotation(Class<T> annotationClass);
            Annotation[] getAnnotations();
            Annotation[] getDeclaredAnnotations();
    }

    说明一下:

    • isAnnotationPresent:判断是否标注了指定注解
    • getAnnotation:获取指定注解,没有则返回null
    • getAnnotations:获取所有注解,包括继承自基类的,没有则返回长度为0的数组
    • getDeclaredAnnotations:获取自身显式标明的所有注解,没有则返回长度为0的数组
  • 相关阅读:
    docker 构建带健康检查的redis镜像
    HP服务器 开启ILO
    [转]如何取得当前正在执行的shell脚本的绝对路径?
    解决方案:centos运行shell脚本时报“$' ': 未找到命令”
    Js控制滚动条
    json_decode时含有中文是解码问题(json_decode返回为null)
    Phaser开源2d引擎 html5游戏框架中文简介
    js 开启video全屏模式
    修改mysql用户名密码 和 PHPmysqlAdmin对应密码修改
    用javascript判断一个html元素是否存在的五种方法:
  • 原文地址:https://www.cnblogs.com/liqiu/p/3407140.html
Copyright © 2020-2023  润新知