好处:

能够读懂别人的代码,特别是框架相关的代码;

让编程更加简洁,代码更加清晰。

使用自定义注解解决问题!!

Java1.5版本引入。

Java中的常见注解

  • @Override:告诉使用者及编译器,该方法覆盖了父类或接口中的同名方法
  • @Deprecated:表示该方法已经过时了。
  • @Suppvisewarnings:忽略deprecated给出的警告。
  • 常见第三方注解:
    • Spring: @Autowired, @Service, @Repository
    • Mybatis: @InsertProvider, @UpdateProvider, @Options

注解分类

  • 按照运行机制分:

    • 源码注解:注解只在源码中存在,编译成class文件就不存在了
    • 编译时注解:注解在源码和.class文件中都存在
    • 运行时注解 :在运行阶段还起作用,甚至会影响运行逻辑的注解 如@Autowired注解
  • 按照来源分:
    • 来自JDK的注解
    • 来自第三方的注解
    • 自己定义的注解
  • 元注解:注解的注解

自定义注解

  • 语法要求

    • 成员类型是受限的,合法的类型包括原始类型及String,Class,Annotation,Enumeration;
    • 如果注解只有一个成员,则成员们必须取名为value(),在使用时可以忽略成员名和赋值号(=);
    • 注解类可以没有成员,没有成员的注解类成为标识注解;
  • 元注解(注解的注解)
    • @Target(……)
    • @Retention:生命周期(SOURCE:只在源码显示编译时丢弃;CLASS:编译时会记录到class中,运行时忽略;RUNTIME:运行时存在,可以通过反射读取)
    • @Inherited:允许子类继承,只能在类或者抽象类间继承,接口是不会继承的。而且继承时只是类的继承,类中的方法并不会继承。
    • @Documented:生成javadoc时会包含信息。
      • 到处一个Javadoc:在工程上点击Export->javadoc->设置路径,通过index.html即可查看你导出的Javadoc
  • 使用自定义注解

解析注解

  • 概念:通过反射获取类、函数或成员上的运行时注解信息,从而实现动态控制程序运行的逻辑。
  • //实例:拿到类名字的解释
    public class ParseAnn {
    public static void main(String[] args) {
    //1.使用类加载器加载类
    try {
    Class c = Class.forName("com.ann.test.Child");
    //2.找到类上面的注解
    boolean isExist = c.isAnnotationPresent(Description.class);
    if(isExist) {
    //3.拿到注解实例
    Description d = (Description) c.getAnnotation(Description.class);
    System.out.println(d.value());
    }
    //4.找到方法上的注解
    Method[] ms = c.getMethods();
    for(Method m : ms) {
    boolean isMExist = m.isAnnotationPresent(Description.class);
    if(isMExist) {
    Description d = (Description) m.getAnnotation(Description.class);
    System.out.println(d.value());
    }
    } //另外一种解析方法
    for(Method m : ms) {
    Annotation[] as = m.getAnnotations();
    for(Annotation a : as) {
    if(a instanceof Description) {
    Description d = (Description)a;
    System.out.println(d.value());
    }
    }
    } } catch (ClassNotFoundException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    }
    }
  • //Child.java信息
    @Description("I am class annotation")
    public class Child implements Person { @Override
    @Description("I am method annotation")
    public String name() {
    // TODO Auto-generated method stub
    return null;
    } @Override
    public int age() {
    // TODO Auto-generated method stub
    return 0;
    } @Override
    public void sing() {
    // TODO Auto-generated method stub } }

实践

  • 项目取自一个公司的持久层框架,用来代替Hibernate的解决方案,核心代码就是通过注解来实现的。
  • 需求:
    • 1.有一张用户表,字段包括用户ID、用户名、昵称、年龄、性别、所在城市、邮箱、手机号。
    • 2.方便的对每个子弹或字段的组合条件进行检索,并打印出SQL。
    • 使用方式要足够简单。
  • private static String query(Object f) {
    StringBuilder sb = new StringBuilder();
    //1.获取到class
    Class c = f.getClass();
    //2.获取到table的名字
    boolean exist = c.isAnnotationPresent(Table.class);
    if(!exist)
    return null;
    Table t = (Table) c.getAnnotation(Table.class);
    String tableName = t.value();
    sb.append("select * from ").append(tableName).append(" where 1=1 ");
    //3.遍历所有的字段
    Field[] fArray = c.getDeclaredFields();
    for(Field field : fArray) {
    //4. 处理每个字段对应的SQL
    //4.1 拿到字段名
    boolean fe = field.isAnnotationPresent(Column.class);
    if(!fe)
    continue;
    // Column column = field.getAnnotation(Column.class);
    // String columnName = column.value();
    //4.2拿到字段值
    String fieldName = field.getName();
    String getMethodName = "get" + fieldName.substring(0, 1).toUpperCase() +
    fieldName.substring(1);
    Object fieldValue = null;
    try {
    Method getMethod = c.getMethod(getMethodName);
    fieldValue = getMethod.invoke(f);
    } catch (Exception e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    //4.3拼装SQL
    if(fieldValue == null ||
    (fieldValue instanceof Integer && (Integer)fieldValue == 0))
    continue;
    if(fieldValue instanceof String) {
    if(((String) fieldValue).contains(",")) {
    String[] values = ((String) fieldValue).split(",");
    sb.append("and ").append(fieldName).append(" in(");
    for(String v : values) {
    sb.append("'").append(v).append("',");
    }
    sb.deleteCharAt(sb.length()-1);
    sb.append(")");
    }
    else
    sb.append("and ").append(fieldName).append("='")
    .append(fieldValue).append("'");
    }
    else
    sb.append("and ").append(fieldName).append("=").append(fieldValue);
    } return sb.toString();
    }

总结

  • 注解的作用范围@Target和生命周期@Retention

    • 作用范围包括:包、类、字段、方法、方法的参数和局部变量
    • 生命周期:源文件SOURCE、编译CLASS、运行RUNTIME
  • 等读懂注解
  • 在实际项目中用注解解决问题,并能自定义注解

最新文章

  1. Java 正则表达式匹配模式[贪婪型、勉强型、占有型]
  2. 利用eclips创建一个maven项目
  3. Erlang第二课 ---- bit串
  4. Windows 下使用 GNUstep 编译并运行 Objective-C 程序
  5. 【STL】-auto_ptr的用法
  6. HDU 1316 How Many Fibs?(java,简单题,大数)
  7. win10安装配置jdk的环境变量
  8. 关于springboot的定时器配置
  9. Spring IoC的原理为什么是反射而不是new
  10. kafka安装与测试
  11. swift 有道 翻译文档(1 定义变量常量,数组字典)
  12. Some notes in Stanford CS106A(1)
  13. 在java1.8下使用jetty报错java.lang.CharSequence cannot be resolved
  14. python函数基础用法
  15. Jupyter Notebook主题字体设置及自动代码补全
  16. 一,php的错误处理和异常处理
  17. canvas之太阳系效果
  18. sql时间格式转换
  19. 解决网页中Waiting (TTFB)数据加载过慢的问题
  20. mysql时间运算

热门文章

  1. JS 定时器,定时调用PHP
  2. Redis缓存数据库的安装与配置(1)
  3. responsive grid
  4. 实用脚本 2 -- Linux下定时执行脚本
  5. CentOS修改网卡名称
  6. 1,理解java中的IO
  7. 【数据结构】 Queue 的简单实现
  8. Qt Qwdget 汽车仪表知识点拆解2 图像放大
  9. Python|花了一天,为大家整理的一套来自外国大佬的密码速查表
  10. mysql修改外部访问权限