Java自定义注解
注解在Java程序设计中是一个很重要的角色,平时我们接触比较多的是第三方注解,比如Spring等框架中的注解。下面看一下自定义注解的简单使用,只演示基础的创建及解析注解。

首先新建一个注解(Annotation),可以直接在Eclipse右键->new->Annotation。在创建界面,我们会看到一些可选项,分别为:Retention、Target、Inherited、Documented。
@Retention
字面意思保留,保持。按照其字面意思很容易理解,也可以理解为生命周期,有三个分类,或者说三个等级:
(1)source:源码级注解。意思是该注解只在源码种存在,编译成class文件就不存在了。
(2)class:编译时注解。意思是在源码及编译后的class文件中均存在。
(3)runtime:运行时注解。在程序运行阶段还会起作用,甚至会对运行逻辑起作用的注解,可以通过反射读取。


@Target
注解的作用域。范围很大,在新建注解时可以看到有以下条目:
文章正文图片

@Inherited
允许子类继承。是一个标识性的元注解(元注解:给注解进行注解的注解,叫做元注解。)。

@Documented
生成JavaDoc的时候会包含注解的相关信息,也属于元注解。

新建Description注解:Description.java
package org.devsong.test;

import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Documented;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

@Retention(RUNTIME)
@Target({ TYPE, METHOD })
@Inherited
@Documented  
public @interface Description {
    String value();
}
成员变量以无参无异常的方式声明,可以用default为成员指定一个默认值,例如,一个名为count的成员,默认值为10: int count() default 10。成员的类型是受限制的,合法的类型包括原始类型String,Class,Annotation,Enumeration当注解只有一个成员的时候,成员名应为value,在赋值时可以忽略成员名和赋值符号(=)

下面新建测试类及测试目标类(简单演示,建在了一个文件中):ParseAnnotation.java
package org.devsong.test;

import java.lang.reflect.Method;

public class ParseAnnotation {
    public static void main(String[] args) {
        try {
            //使用类加载器加载类
            Class c = Class.forName("org.devsong.test.Foo");    
            System.out.println("==========开始解析类注解==========");
            if(c.isAnnotationPresent(Description.class)) {
                //获取注解实例
                Description desc = (Description) c.getAnnotation(Description.class);
                //获取注解成员值并输出
                System.out.println(desc.value());
            }
            
            System.out.println("==========开始解析方法注解==========");
            Method[] methods = c.getMethods();
            //遍历所有的方法
            for(Method m : methods) {            
                if(m.isAnnotationPresent(Description.class)) {
                    Description desc = (Description) m.getAnnotation(Description.class);
                    System.out.println(desc.value());
                }
            }
            
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

//测试目标类
@Description("class annotation")
class Foo{
    @Description("method annotation 1")
    public void sayHello() {
        System.out.println("hello");
    }
    
    @Description("method annotation 2")
    public void sayHi() {
        System.out.println("hi");
    }
}
运行结果如下:
==========开始解析类注解==========
class annotation
==========开始解析方法注解==========
method annotation 1
method annotation 2

当然除了上述方法之外,也可以用getAnnotations()方法获取当前类的所有注解,然后再遍历每一个注解进行处理。只有运行时注解才会被取到。

另外,用@Inherited注解了当前注解就表示当前注解允许子类继承,值得注意的是仅仅只是继承类上面的注解,而不会继承方法上的注解。也就是说下面类只从Foo类中继承了类注解(@DEscription("class annotation")),而不会继承方法注解。
//测试目标类二
//只会从Foo类中继承了类注解而不会继承方法注解
class Foo1 extends Foo{
    @Override
    public void sayHello() {
        System.out.println("hello");
    }
    
    @Override
    public void sayHi() {
        System.out.println("hi");
    }
}
若运行类解析对Foo1类进行注解解析,将只会得到以下结果:
==========开始解析类注解==========
class annotation
==========开始解析方法注解==========





It's
欢迎访问本站,欢迎留言、分享、点赞。愿您阅读愉快!
*转载请注明出处,严禁非法转载。
https://www.devsong.org
QQ留言 邮箱留言
头像
引用:
取消回复
提交
涂鸦
涂鸦
热门