美文网首页
第11章 注解

第11章 注解

作者: AndroidMaster | 来源:发表于2018-03-30 15:18 被阅读14次

    Annotation其实就是代码里的特殊标记,可以在编译,类加载,运行的时候被读取,并执行相应的处理。在不改变原有逻辑的情况下,在源文件嵌入一些补充信息。一条重要原则:仅仅使用注解来标识程序元素,对程序不会造成任何影响,要让注解起作用,必须为这些注解提供注解处理工具。

    一、基本Annotation

    • @Override 只能修饰方法,强制子类必须覆盖父类的方法
    • @Deprecated 表示某个程序元素(类、方法、接口等)已经过时,若其他程序使用该元素,将会给出警告
    • @SuppressWarnings 被修饰的程序元素取消显示指定的警告,会同时作用于该程序元素下的所有的子元素

    二、自定义Annotation

    1、定义Annotation

    定义新的Annotation,使用@interface关键字,与定义一个接口非常相似。所有的注解都继承了Annotation接口。

    public @interface Testable{
        
    }
    

    使用Annotation的语法,非常类似于public,final等修饰符(一般单独放一行),通常用于修饰程序中的类 、接口、变量、方法等

    public class MyClass {
        @Testable
        public void info() {
    
        }
    }
    

    Annotation中还可以带成员变量,用无参数的方法来声明。方法名定义了成员变量的名字,返回值定义了成员变量的类型。语法与定义接口的语法非常相似。若没有定义默认值,则必须赋值。

    public @interface Testable {
        String name();
        int age() default 19;//已经设置默认值,使用时可以不赋值
    }
    //使用
    public class MyClass {
        @Testable(name="xiangyaohui")
        public void info() {
    
        }
    }
    

    标记Annotation:没有成员变量,仅使用自身的存在与否,来为我们提供信息。
    元数据Annotation:包含成员变量的Annotation,因为他们可以接受更多的元数据。

    2、提取Annotation信息

    AnnotatedElement接口中的三个方法

    - <T extends Annotation> T getAnnotation(Class<T> aClass) //返回该类程序元素上,指定类型的注解,若该类型的注解不存在,返回null
    - Annotation[] getAnnotations()   //返回程序元素存在的所有注解
    - boolean isAnnotationPresent(Class<? extends Annotation> aClass)   //判定该程序元素上是否包含指定类型的注解
    

    AnnotatedElement接口的实现类:
    Class
    Contrustor
    Field
    Method
    Package

    2.1、例子一

    仅仅是一个标记Annotation,没有成员变量

    public @interface Testable {
    }
    
    public class MyClass {
        @Testable
        public void m1() {
    
        }
        public void m2() {
    
        }
    }
    
    public class TestProcessor {
        public static void process(String clazz) throws ClassNotFoundException {
            for (Method m : Class.forName(clazz).getMethods()) {
                //如果包含Testable标记注解
                if (m.isAnnotationPresent(Testable.class)) {
                    try {
                        //调用m方法
                        m.invoke(null);
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    

    其实注解很简单,就是为源码添加一些特殊的标记,这些标记可以通过反射获取,获取到之后做出相应的处理。

    2.2、例子二

    public @interface ClickListenerFor {
        //用于保存监听器实现类
        String listener();
    }
    
    public class ClickListenerProcessor {
        public static void process(Object obj) {
            try {
                Class clazz = obj.getClass();
                for (Field field : clazz.getFields()) {
                    field.setAccessible(true);
                    ClickListenerFor c = field.getAnnotation(ClickListenerFor.class);
                    if (c !=null){
                        //获取元数据
                        Class listenerClazz = Class.forName(c.listener());
                        //
                        View.OnClickListener click = (View.OnClickListener) listenerClazz.newInstance();
                        //获取field 实际对应的对象
                        Button button = (Button) field.get(obj);
                        //添加事件
                        button.setOnClickListener(click);
                    }
                }
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    }
    
    public class MainActivity extends Activity {
        @ClickListenerFor(listener = "OkClickListener")
        private Button okButton;
        @ClickListenerFor(listener = "CancelClickListener")
        private Button cancelButton;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            Button button1 = findViewById(R.id.button1);
            Button button2 = findViewById(R.id.button2);
            ClickListenerProcessor.process(this);
        }
    
        class OkClickListener implements View.OnClickListener {
            @Override
            public void onClick(View view) {
                //点击了确定按钮
            }
        }
    
        class CancelClickListener implements View.OnClickListener {
            @Override
            public void onClick(View view) {
                //点击了取消按钮
            }
        }
    }
    

    三、元注解

    @Retention

    @Test

    @Documented

    @Inherited

    四、使用APT来处理Annotation

    相关文章

      网友评论

          本文标题:第11章 注解

          本文链接:https://www.haomeiwen.com/subject/vmklfftx.html