Annotation

来源:互联网 发布:大庆石化公司网络培训 编辑:程序博客网 时间:2024/04/19 22:19

Annotation是代码里的特殊标记,这些标记可以在编译,类加载、运行时被读取,并执行相应的处理。通过使用注解,程序开发人员可以通过这些补充信息进行验证或者进行部署。


Annotation就像修饰符一样,可用于修饰包、类、构造器、方法、成员变量、参数、局部变量的声明,这些信息被存储在Annotation的"name=value"对中。

Annotation能被用来为程序元素(类、方法、成员变量)设置元数据。Annotation不影响程序代码的执行,无论是删除、增加Annotation。


基本Annotation

@Override限定重写父类方法

@Deprecated标记已过时

@SuppressWarnings(name="value")抑制编译器警告

@SafeVarargs抑制堆污染警告

堆污染是指把一个不带泛型的对象赋给一个泛型的常量

@FunctionalInterface指定某个接口必须是函数式接口(只能修饰接口)


根据Annotation是否包含成员变量,将Annotation分为如下两类:

1、标记Annotation,没有定义成员变量的Annotation类型被称为标记。

2、元数据Annotation,包含成员变量,可以接收更多的元数据。


元Annotation

@Retention指定被修饰的Annotation可以保留多长时间

@Target执行被修饰的Annotation用于修饰哪些程序单元

@Documented指定被修饰的Annotation类将被javadoc工具提取成文档,如果定义Annotation类时使用了@Documented修饰,则使用该Annotation修饰的程序元素的API文档将会包含该Annotation说明。

@Inherited指定被修饰的Annotation具有继承性,如果某个类使用了@Inheritable修饰,则该类的子类自动使用@Inheritable修饰。


自定义Annotation:

public @interface MyTag{    String name() default "yeeku";    int age() default 32;}

提取Annotation信息:

java.lang.reflect包下包含实现反射功能的工具类,也增加了读取运行时Annotation的能力。只有当定义Annotation时使用了@Retention(RetentionPolicy.RUNTIME)修饰,该@Retention才会在运行时可见,JVM才会在装在*.class文件时读取保存在class文件中的Annotation。

Class<?> clazz = Class.forName("annotation.case5.Test");Annotation[] aArrays = clazz.getMethod("info").getAnnotations();for(Annotation an:aArrays){    System.out.println(an);}for(Annotation tag:aArrays){    if(tag instanceof MyTag){        System.out.println(((MyTag) tag).name());        System.out.println(((MyTag) tag).age());    }}


使用Annotation:

为了让Annotation起作用,要为注解提供一个注解处理工具,如果目标类使用了注解修饰,就通过反射来运行测试方法。

//定义一个标记注解@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.METHOD)public @interface Testable {}//使用@Testable来标记这些方法是可测试的public class MyTest {    @Testable    public static void m1(){            }        public static void m2(){            }        @Testable    public static void m3(){        throw new IllegalArgumentException("参数出错了!");    }        public static void m4(){            }        @Testable    public static void m5(){            }        public static void m6(){            }}//为注解提供一个注解处理工具public class ProcessorTest {    public static void process(String clazz) throws ClassNotFoundException{        int passed=0;        int failed=0;                for (Method m : Class.forName(clazz).getMethods()) {            if(m.isAnnotationPresent(Testable.class)){                try {                    m.invoke(null);                    passed++;                } catch (Exception e) {                    // TODO: handle exception                    System.out.println("方法"+m+"运行失败,异常:"+e.getCause());                    failed++;                }            }        }        System.out.println("共运行了:"+(passed+failed)+"个方法,其中:\n"+"失败了:"+failed+"个,成功了:"+passed+"个!");    }}//测试主类public class RunTests {    public static void main(String[] args) throws ClassNotFoundException {        // TODO Auto-generated  stub        ProcessorTest.process("annotatiomethodn.MyTest");    }}


其实Annotation就是对源代码增加一些特殊标记,这些标记可通过反射获取,当程序获取这些特殊标记后,程序可以做出相应的处理。

//为程序绑定事件监听器@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)public @interface ActionListenerFor {Class<? extends ActionListener> listener();}//测试类<pre name="code" class="java">public class AnnotationTest {private JFrame mainWin=new JFrame("使用注解绑定事件监听器");@ActionListenerFor(listener=OkListener.class)private JButton ok=new JButton("确定");@ActionListenerFor(listener=CancelListener.class)private JButton cancel=new JButton("取消");public void init() {JPanel jp=new JPanel();jp.add(ok);jp.add(cancel);mainWin.add(jp);ActionListenerInstaller.processAnnotations(this);mainWin.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);mainWin.pack();mainWin.setVisible(true);}public static void main(String[] args){new AnnotationTest().init();}}class OkListener implements ActionListener{@Overridepublic void actionPerformed(ActionEvent e) {// TODO Auto-generated method stubJOptionPane.showMessageDialog(null, "单机了确认按钮");}}class CancelListener implements ActionListener{@Overridepublic void actionPerformed(ActionEvent e) {// TODO Auto-generated method stubJOptionPane.showMessageDialog(null, "单机了取消按钮");}}//注解处理工具public class ActionListenerInstaller {    public static void processAnnotations(Object object){        Class<? extends Object> c1=object.getClass();        System.out.println(c1.getDeclaredFields().length);        try {            for (Field f : c1.getDeclaredFields()) {                f.setAccessible(true);                ActionListenerFor a = f.getAnnotation(ActionListenerFor.class);                Object fObject=f.get(object);                if(a!=null&&fObject!=null&&fObject instanceof AbstractButton){                    Class<? extends ActionListener> listenerClazz=a.listener();                    ActionListener a1=listenerClazz.newInstance();                    AbstractButton ab=(AbstractButton) fObject;                    ab.addActionListener(a1);                }            }        } catch (Exception e) {            // TODO Auto-generated catch block            e.printStackTrace();        }    }} 

java8新增了重复注解,允许使用多个相同类型的Annotation来修饰同一个类。

为了使注解改造成重复注解,需要使用@Repeatable来修饰该注解,还得创造一个容器注解来包含这个value();为了获取一个类中的多个Annotation注解,可以使用java8新增的getDeclaredAnnotationByType()方法:

@Retention(RetentionPolicy.RUNTIME)@Repeatable(FkTags.class)@Target(ElementType.TYPE)public @interface FkTag {String name() default "疯狂软件";int age();}@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.TYPE)public @interface FkTags {    FkTag[] value();}@FkTag(age=5)@FkTag(name="疯狂java",age=9)public class FkTagTest {    public static void main(String[] args) {        // TODO Auto-generated method stub        Class<FkTagTest> clazz=FkTagTest.class;        FkTag[] tags=clazz.getDeclaredAnnotationsByType(FkTag.class);        for (FkTag fkTag : tags) {            System.out.println(fkTag.name()+"-->"+fkTag.age());        }                FkTags container = clazz.getDeclaredAnnotation(FkTags.class);        System.out.println(container);    }}

APT(Annotation Processing Tool)是一种注解处理工具,对源代码文件进行检测,并找出源文件所包含的Annotation信息,针对Annotation信息进行额外的处理。例如通过注解可以在java源文件中放置一些Annotation,使用APT工具就可以生成另一份XML文件。




0 0
原创粉丝点击