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文件。
- annotation
- Annotation
- Annotation
- Annotation
- Annotation
- Annotation
- Annotation
- Annotation
- annotation
- Annotation
- Annotation
- @Annotation
- Annotation
- Annotation
- Annotation
- Annotation
- Annotation
- Annotation
- 【水水水】678A - Johny Likes Numbers
- POJ - 3281 Dining 网络流
- hdu 4513(manacher+dp)
- Android 简单登录界面
- gdb调试Clang2.6 (clang-cc)
- Annotation
- HttpURLConnection简介
- Go - 基础知识二
- WebView相关
- COOHxNH2
- Power Shell 使用图解2
- 面试题 -- 下载并安装APK
- 保护模式学习笔记:IDT
- facebook数据采集——利用BigPipe技术和xpath解析数据