前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >TIII-Android技术篇之注解Annotation

TIII-Android技术篇之注解Annotation

作者头像
张风捷特烈
发布2018-09-29 11:24:07
4350
发布2018-09-29 11:24:07
举报
文章被收录于专栏:Android知识点总结
开幕:初见
首先看一下家喻户晓的@Override注解:添加此注解,如果是非覆写的方法,就会报错
代码语言:javascript
复制
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
再先看一下@Deprecated注解:添加此注解,如果是过时的方法,就会画线提示
代码语言:javascript
复制
@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;
}
我们这个群体应该很擅长归纳事物的共性,然后总结出一丝规律
代码语言:javascript
复制
可以看到的是:
public @interface 注解名{
    
}
因此,可依照这样自己写一个注解类:
public @interface APerson {

}
然后新建一个Person类看看能不能用:
@APerson
public class Person {

}
编译器没报错,看了可以,于是你的第一个没用的注解就由此诞生,开幕止。
第一幕:相识:
原标签
1:@Retention(注解存活期):接受一个RetentionPolicy类型的枚举常量
代码语言:javascript
复制
//源码的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
}
创建一个运行期的注解
代码语言:javascript
复制
@Retention(RetentionPolicy.RUNTIME)
public @interface APerson {

}
2:@Target(目标):接受一个ElementType类型的枚举常量
代码语言:javascript
复制
//源码枚举类: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。
已经同注解进行了基本的对话(了解),第二幕止。
第三幕:交涉
改善一下我们的注解
代码语言:javascript
复制
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对象,再得到其方法
代码语言:javascript
复制
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();
    }
}
输出结果
代码语言:javascript
复制
my name is 捷特,and I am 24 years old.
现在测试一下@Inherited(继承):
代码语言:javascript
复制
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 {

}
运行:报错
代码语言:javascript
复制
Exception in thread "main" java.lang.NullPointerException
    at top.toly.注解.Person.say(Person.java:14)
    at top.toly.注解.Person.main(Person.java:22)
添加@Inherited注解
代码语言:javascript
复制
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Inherited
public @interface APerson {
    public String name() default "捷特";
    public int age() default 24;
}
运行:
代码语言:javascript
复制
//
my name is 捷特,and I am 24 years old.
这时你已经可以通过注解来获取信息了
第四幕:共鸣
代码语言:javascript
复制
人类创造了刀,有些人用它雕精美的艺术品,有人依靠它成为江湖浪客,有人以它护生,有人用它杀生。
成败善恶并非工具的荣辱,也非是锻造它的人,一切只取决于握刀人的本性与技艺。
下面通过两个简单示例实战一下
示例一:声明:下面的案例借鉴并修改于:https://blog.csdn.net/briblue/article/details/73824058
代码语言:javascript
复制
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 {

}
代码语言:javascript
复制
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("\n\r  caused by ");
                    //记录测试过程中,发生的异常的名称
                    log.append(e.getCause().getClass().getSimpleName());
                    log.append("\n\r");
                    //记录测试过程中,发生的异常的具体信息
                    log.append(e.getCause().getMessage());
                    log.append("\n\r");
                }
            }
        }

        log.append(clazz.getSimpleName());
        log.append(" has  ");
        log.append(errornum);
        log.append(" error.");

        // 生成测试报告
        System.out.println(log.toString());

    }
}
代码语言:javascript
复制
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();
    }

}
代码语言:javascript
复制
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");
    }
}

输出:

代码语言:javascript
复制
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.
代码语言:javascript
复制
可以看到未加注解的方法,即使错了也不会检查到。
注解更像提示你一下到这要不要做些什么事,具体逻辑还需要具体的类来实现。
唯一的优势在于你知道了程序已经运行到注解处,还有你可以获取到注解中的字段值。
示例二:根据一个bean对象,来输处MySQL的查询语句
1.数据库列(字段)注解
代码语言:javascript
复制
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.数据库表注解
代码语言:javascript
复制
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篇)
代码语言:javascript
复制
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:使用注解辅助得到查询语句
代码语言:javascript
复制
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.测试端
代码语言:javascript
复制
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.打印结果
代码语言:javascript
复制
SELECT * FROM sword WHERE 1=1 and name='炽燃' and atk=2000
用MySQL验证一下:

20180523152021788.png

终幕

后记、
1.声明:

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

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018.09.10 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 开幕:初见
    • 首先看一下家喻户晓的@Override注解:添加此注解,如果是非覆写的方法,就会报错
      • 再先看一下@Deprecated注解:添加此注解,如果是过时的方法,就会画线提示
        • 我们这个群体应该很擅长归纳事物的共性,然后总结出一丝规律
          • 编译器没报错,看了可以,于是你的第一个没用的注解就由此诞生,开幕止。
      • 第一幕:相识:
        • 原标签
          • 1:@Retention(注解存活期):接受一个RetentionPolicy类型的枚举常量
            • 创建一个运行期的注解
          • 2:@Target(目标):接受一个ElementType类型的枚举常量
            • 3:@Inherited(继承):子类继承父类的注解
              • 4:@Repeatable(可重复)
                • 5:@Documented:能够将注解中的元素包含到 Javadoc。
                  • 已经同注解进行了基本的对话(了解),第二幕止。
              • 第三幕:交涉
                • 改善一下我们的注解
                  • 使用反射获取APerson对象,再得到其方法
                    • 输出结果
                      • 现在测试一下@Inherited(继承):
                        • 运行:报错
                          • 添加@Inherited注解
                            • 运行:
                              • 这时你已经可以通过注解来获取信息了
                          • 第四幕:共鸣
                          • 下面通过两个简单示例实战一下
                            • 示例一:声明:下面的案例借鉴并修改于:https://blog.csdn.net/briblue/article/details/73824058
                              • 示例二:根据一个bean对象,来输处MySQL的查询语句
                                • 1.数据库列(字段)注解
                                • 2.数据库表注解
                                • 3.bean对象Sworld:曾经创建过一个sword的数据库,正好拿来用。(对MySQL不熟悉的可以看我的MySQL篇)
                                • 4.核心类:QueryUtil:使用注解辅助得到查询语句
                                • 5.测试端
                                • 6.打印结果
                                • 用MySQL验证一下:
                            • 终幕
                            • 后记、
                              • 1.声明:
                              相关产品与服务
                              云数据库 MySQL
                              腾讯云数据库 MySQL(TencentDB for MySQL)为用户提供安全可靠,性能卓越、易于维护的企业级云数据库服务。其具备6大企业级特性,包括企业级定制内核、企业级高可用、企业级高可靠、企业级安全、企业级扩展以及企业级智能运维。通过使用腾讯云数据库 MySQL,可实现分钟级别的数据库部署、弹性扩展以及全自动化的运维管理,不仅经济实惠,而且稳定可靠,易于运维。
                              领券
                              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档