zoukankan      html  css  js  c++  java
  • TVI-Android技术篇之注解Annotation

    开幕:初见

    首先看一下家喻户晓的@Override注解:添加此注解,如果是非覆写的方法,就会报错
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.SOURCE)
    public @interface Override {
    }
    
    再先看一下@Deprecated注解:添加此注解,如果是过时的方法,就会画线提示
    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, MODULE, PARAMETER, TYPE})
    public @interface Deprecated {
        String since() default "";
        boolean forRemoval() default false;
    }
    
    我们这个群体应该很擅长归纳事物的共性,然后总结出一丝规律
    可以看到的是:
    public @interface 注解名{
        
    }
    因此,可依照这样自己写一个注解类:
    public @interface APerson {
    
    }
    然后新建一个Person类看看能不能用:
    @APerson
    public class Person {
    
    }
    
    编译器没报错,看了可以,于是你的第一个没用的注解就由此诞生,开幕止。

    第一幕:相识:

    原标签
    1:@Retention(注解存活期):接受一个RetentionPolicy类型的枚举常量
    //源码的RetentionPolicy枚举
    public enum RetentionPolicy {
        /**
         * Annotations are to be discarded by the compiler.
         * 注解将会被编译器删除
         */
        SOURCE,
    
        /**
         * Annotations are to be recorded in the class file by the compiler
         * but need not be retained by the VM at run time.  This is the default
         * behavior.
         * 编译器会将注解保留在字节码文件中,但VM不会再运行期间保留它。这是默认行为
         */
        CLASS,
    
        /**
         * Annotations are to be recorded in the class file by the compiler and
         * retained by the VM at run time, so they may be read reflectively.
         * 编译器会将注解保留在字节码文件中,VM也会在运行期间保留它。(所以他们可以通过反射性被读取)
         * @see java.lang.reflect.AnnotatedElement
         */
        RUNTIME
    }
    
    
    创建一个运行期的注解
    @Retention(RetentionPolicy.RUNTIME)
    public @interface APerson {
    
    }
    
    2:@Target(目标):接受一个ElementType类型的枚举常量
    //源码枚举类:ElementType
    public enum ElementType {
        /** Class, interface (including annotation type), or enum declaration */
        //声明类,接口(包括注解类型),或者枚举
        TYPE,   
        /** Field declaration (includes enum constants) */
        //声明字段(包括枚举常量)
        FIELD,  
    
        /** Method declaration */
        //声明方法
        METHOD,
    
        /** Formal parameter declaration */
        //声明方法参数
        PARAMETER,
    
        /** Constructor declaration */
        //声明构造函数
        CONSTRUCTOR,
    
        /** Local variable declaration */
        //声明局部变量
        LOCAL_VARIABLE,
    
        /** Annotation type declaration */
        //声明注解
        ANNOTATION_TYPE,
    
        /** Package declaration */
        //声明包
        PACKAGE,
    
        /**
         * Type parameter declaration
         *  声明参数类型
         * @since 1.8
         */
        TYPE_PARAMETER,
    
        /**
         * Use of a type
         *  
         * @since 1.8
         */
        TYPE_USE,
    
        /**
         * Module declaration.
         *  声明模块
         * @since 9
         */
        MODULE
    }
    
    3:@Inherited(继承):子类继承父类的注解
    4:@Repeatable(可重复)
    5:@Documented:能够将注解中的元素包含到 Javadoc。
    已经同注解进行了基本的对话(了解),第二幕止。

    第三幕:交涉

    改善一下我们的注解
    package top.toly.注解;
    
    import java.lang.annotation.*;
    
    /**
     * 作者:张风捷特烈
     * 时间:2018/5/22:8:20
     * 邮箱:1981462002@qq.com
     * 说明:注解类
     */
    
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE)
    public @interface APerson {
        public String name() default "捷特";
        public int age() default 24;
        
    }
    
    使用反射获取APerson对象,再得到其方法
    package top.toly.注解;
    
    /**
     * 作者:张风捷特烈
     * 时间:2018/5/22:8:21
     * 邮箱:1981462002@qq.com
     * 说明:注解测试端
     */
    @APerson(name = "捷特", age = 24)
    public class Person {
        APerson aPerson = getClass().getAnnotation(APerson.class);
    
        public void say() {
            String name = aPerson.name();
            int age = aPerson.age();
            System.out.println("my name is "+name+",and I am "+age+"years old");
        }
    
    
        public static void main(String[] args) {
            Person person = new Person();
            person.say();
        }
    }
    
    输出结果
    my name is 捷特,and I am 24 years old.
    
    现在测试一下@Inherited(继承):
    package top.toly.注解;
    
    /**
     * 作者:张风捷特烈
     * 时间:2018/5/22:8:21
     * 邮箱:1981462002@qq.com
     * 说明:注解测试端
     */
    @APerson(name = "捷特", age = 24)
    public class Person {
        APerson aPerson = getClass().getAnnotation(APerson.class);
    
        public void say() {
            String name = aPerson.name();
            int age = aPerson.age();
            System.out.println("my name is "+name+",and I am "+age+" years old.");
        }
    
    
        public static void main(String[] args) {
            Student student = new Student();
            student.say();
        }
    }
    
    class Student extends Person {
    
    }
    
    
    运行:报错
    Exception in thread "main" java.lang.NullPointerException
        at top.toly.注解.Person.say(Person.java:14)
        at top.toly.注解.Person.main(Person.java:22)
    
    添加@Inherited注解
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE)
    @Inherited
    public @interface APerson {
        public String name() default "捷特";
        public int age() default 24;
    }
    
    
    运行:
    //
    my name is 捷特,and I am 24 years old.
    
    这时你已经可以通过注解来获取信息了

    第四幕:共鸣

    人类创造了刀,有些人用它雕精美的艺术品,有人依靠它成为江湖浪客,有人以它护生,有人用它杀生。
    成败善恶并非工具的荣辱,也非是锻造它的人,一切只取决于握刀人的本性与技艺。
    

    下面通过两个简单示例实战一下

    示例一:声明:下面的案例借鉴并修改于:https://blog.csdn.net/briblue/article/details/73824058
    package top.toly.注解;
    
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    
    /**
     * 作者:张风捷特烈
     * 时间:2018/5/22:10:16
     * 邮箱:1981462002@qq.com
     * 说明:注解类
     */
    @Retention(RetentionPolicy.RUNTIME)
    public @interface ADebug {
    
    }
    
    
    package top.toly.注解;
    
    import java.lang.reflect.Method;
    
    /**
     * 作者:张风捷特烈
     * 时间:2018/5/22:10:17
     * 邮箱:1981462002@qq.com
     * 说明:测试工具类
     */
    public class Debug {
    
        public static void debug(String clazz_name) {
    
            Class<?> clazz = null;//获取测试类字节码文件
            Object testobj = null;//通过字节码获取实例
            try {
                clazz = Class.forName(clazz_name);
                testobj = clazz.newInstance();
            } catch (Exception e) {
                e.printStackTrace();
            }
    
            Method[] method = clazz.getDeclaredMethods();//通过字节码获取所有方法
            //用来记录测试产生的 log 信息
            StringBuilder log = new StringBuilder();
            // 记录异常的次数
            int errornum = 0;
    
            for (Method m : method) {
                // 只有被 @ADebug 标注过的方法才进行测试
                if (m.isAnnotationPresent(ADebug.class)) {
                    try {
                        m.setAccessible(true);
                        m.invoke(testobj, null);//执行方法
                    } catch (Exception e) {
                        errornum++;
                        log.append("错误"+errornum+":"+m.getName()+"() has error:");
                        log.append("
    
      caused by ");
                        //记录测试过程中,发生的异常的名称
                        log.append(e.getCause().getClass().getSimpleName());
                        log.append("
    
    ");
                        //记录测试过程中,发生的异常的具体信息
                        log.append(e.getCause().getMessage());
                        log.append("
    
    ");
                    }
                }
            }
    
            log.append(clazz.getSimpleName());
            log.append(" has  ");
            log.append(errornum);
            log.append(" error.");
    
            // 生成测试报告
            System.out.println(log.toString());
    
        }
    }
    
    
    
    package top.toly.注解;
    
    /**
     * 作者:张风捷特烈
     * 时间:2018/5/22:10:18
     * 邮箱:1981462002@qq.com
     * 说明:待测试类
     */
    public class BugTest {
        @ADebug
        public void say(){
            System.out.println(Integer.parseInt("a"));
        }
        @ADebug
        public void jia(){
            System.out.println("1+1="+1+1);
        }
        @ADebug
        public void jian(){
            System.out.println("1-1="+(1-1));
        }
        @ADebug
        public void cheng(){
            System.out.println("3 x 5="+ 3*5);
        }
        @ADebug
        public void chu(){
            System.out.println("6 / 0="+ 6 / 0);
        }
    
        public void resay(){
            say();
        }
    
    }
    
    
    package top.toly.注解;
    
    /**
     * 作者:张风捷特烈
     * 时间:2018/5/22:10:28
     * 邮箱:1981462002@qq.com
     * 说明:运行端
     */
    public class Client {
        public static void main(String[] args) {
            Debug.debug("top.toly.注解.BugTest");
        }
    }
    
    

    输出:

    1-1=0
    3 x 5=15
    1+1=11
    错误1:say() has error:
      caused by NumberFormatException
    For input string: "a"
    错误2:chu() has error:
      caused by ArithmeticException
    / by zero
    BugTest has  2 error.
    
    可以看到未加注解的方法,即使错了也不会检查到。
    注解更像提示你一下到这要不要做些什么事,具体逻辑还需要具体的类来实现。
    唯一的优势在于你知道了程序已经运行到注解处,还有你可以获取到注解中的字段值。
    
    示例二:根据一个bean对象,来输处MySQL的查询语句
    1.数据库列(字段)注解
    package top.toly.注解.test;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    /**
     * 作者:张风捷特烈
     * 时间:2018/5/22:23:27
     * 邮箱:1981462002@qq.com
     * 说明:数据库列(字段)注解
     */
    
    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Column {
        String value();
    }
    
    
    2.数据库表注解
    package top.toly.注解.test;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    /**
     * 作者:张风捷特烈
     * 时间:2018/5/22:23:27
     * 邮箱:1981462002@qq.com
     * 说明:数据库表注解
     */
    
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Table {
        String value();
    }
    
    
    3.bean对象Sworld:曾经创建过一个sword的数据库,正好拿来用。(对MySQL不熟悉的可以看我的MySQL篇)
    package top.toly.注解.test.bean;
    
    import top.toly.注解.test.Column;
    import top.toly.注解.test.Table;
    
    /**
     * 作者:张风捷特烈
     * 时间:2018/5/23:14:47
     * 邮箱:1981462002@qq.com
     * 说明:
     */
    @Table("sword")
    public class Sword {
        @Column("id")
        private int id;
        @Column("name")
        private String name;
        @Column("atk")
        private int atk;
        @Column("hit")
        private int hit;
        @Column("crit")
        private int crit;
        @Column("attr_id")
        private int attr_id;
        @Column("type_id")
        private int type_id;
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAtk() {
            return atk;
        }
    
        public void setAtk(int atk) {
            this.atk = atk;
        }
    
        public int getHit() {
            return hit;
        }
    
        public void setHit(int hit) {
            this.hit = hit;
        }
    
        public int getCrit() {
            return crit;
        }
    
        public void setCrit(int crit) {
            this.crit = crit;
        }
    
        public int getAttr_id() {
            return attr_id;
        }
    
        public void setAttr_id(int attr_id) {
            this.attr_id = attr_id;
        }
    
        public int getType_id() {
            return type_id;
        }
    
        public void setType_id(int type_id) {
            this.type_id = type_id;
        }
    }
    
    
    4.核心类:QueryUtil:使用注解辅助得到查询语句
    package top.toly.注解.test;
    
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    
    /**
     * 作者:张风捷特烈
     * 时间:2018/5/23:14:53
     * 邮箱:1981462002@qq.com
     * 说明:使用注解辅助得到查询语句
     */
    public class QueryUtil {
        public static String query(Object o) {
            StringBuffer sb = new StringBuffer();
    
            //1.获取class
            Class<?> aClass = o.getClass();
            //2.获取表名
            boolean exist = aClass.isAnnotationPresent(Table.class);
            if (exist) {
                Table table = aClass.getAnnotation(Table.class);
                String tableName = table.value();
                sb.append("SELECT * FROM ").append(tableName).append(" WHERE 1=1");
                //3.遍历字段
                Field[] fields = aClass.getDeclaredFields();
                for (Field field : fields) {
                    //4.处理字段对应的sql
                    boolean b = field.isAnnotationPresent(Column.class);
                    if (!b) {
                        continue;
                    }
                    Column column = field.getAnnotation(Column.class);
                    String columnName = column.value();
                    String fieldName = field.getName();
                    String getMethodName = "get" + fieldName.substring(0, 1)
                            .toUpperCase() + fieldName.substring(1);
                    Object fieldValue = null;
                    try {
                        Method getMethod = aClass.getMethod(getMethodName);
                        fieldValue = getMethod.invoke(o);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    //拼装sql
                    if (fieldValue == null || (fieldValue instanceof Integer && (Integer) fieldValue == 0)) {
                        continue;
                    }
                    sb.append(" and ").append(fieldName);
                    if (fieldValue instanceof String) {
                        String value = (String) fieldValue;
                        if (value.contains(",")) {
                            String[] strings = value.split(",");
                            sb.append(" in(");
                            for (String string : strings) {
                                sb.append("'").append(string).append("'").append(",");
                            }
                            sb.deleteCharAt(sb.length() - 1);
                            sb.append(")");
                        }else {
                            sb.append("=").append("'" + fieldValue + "'");
                        }
                    }else {
                        sb.append("=").append(fieldValue);
                    }
                }
            }
            return sb.toString();
        }
    }
    
    
    5.测试端
    package top.toly.注解.test;
    
    import top.toly.注解.test.bean.Sword;
    
    /**
     * 作者:张风捷特烈
     * 时间:2018/5/23:14:54
     * 邮箱:1981462002@qq.com
     * 说明:测试端
     */
    public class Client {
        public static void main(String[] args) {
            Sword sabar = new Sword();
            sabar.setName("炽燃");
            sabar.setAtk(2000);
    
            System.out.println(QueryUtil.query(sabar));
    
        }
    }
    
    
    6.打印结果
    SELECT * FROM sword WHERE 1=1 and name='炽燃' and atk=2000
    
    用MySQL验证一下:
    9414344-8cbeada52c365afb.png
    20180523152021788.png

    终幕


    后记、

    1.声明:

    [1]本文由张风捷特烈原创,转载请注明
    [2]欢迎广大编程爱好者共同交流
    [3]个人能力有限,如有不正之处欢迎大家批评指证,必定虚心改正
    [4]你的喜欢与支持将是我最大的动力

    2.连接传送门:

    更多安卓技术欢迎访问:安卓技术栈
    我的github地址:欢迎star
    简书首发,腾讯云+社区同步更新
    张风捷特烈个人网站,编程笔记请访问:http://www.toly1994.com

    3.联系我

    QQ:1981462002
    邮箱:1981462002@qq.com
    微信:zdl1994328

    4.欢迎关注我的微信公众号,最新精彩文章,及时送达:
    9414344-c474349cd3bd4b82.jpg
    公众号.jpg
  • 相关阅读:
    Educational Codeforces Round 67 D. Subarray Sorting
    2019 Multi-University Training Contest 5
    Educational Codeforces Round 69 (Rated for Div. 2) E. Culture Code
    Educational Codeforces Round 69 D. Yet Another Subarray Problem
    2019牛客暑期多校训练第六场
    Educational Codeforces Round 68 E. Count The Rectangles
    2019牛客多校第五场题解
    2019 Multi-University Training Contest 3
    2019 Multi-University Training Contest 2
    [模板] 三维偏序
  • 原文地址:https://www.cnblogs.com/toly-top/p/9781885.html
Copyright © 2011-2022 走看看