zoukankan      html  css  js  c++  java
  • 有用的Java注解

    好处:

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

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

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

    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();
              }
          }
      }
      View Code 
    • //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
      
          }
      
      }
      View Code

    实践

    • 项目取自一个公司的持久层框架,用来代替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();
          }
      View Code
       

    总结

    • 注解的作用范围@Target和生命周期@Retention
      • 作用范围包括:包、类、字段、方法、方法的参数和局部变量
      • 生命周期:源文件SOURCE、编译CLASS、运行RUNTIME
    • 等读懂注解
    • 在实际项目中用注解解决问题,并能自定义注解
  • 相关阅读:
    1309:【例1.6】回文数(Noip1999)
    1168:大整数加法
    1308:【例1.5】高精除
    邻接表存图
    [NOIP2010]关押罪犯(并查集)
    [NOI2001]食物链(并查集)
    最小生成树-Prim算法和Kruskal算法[转]
    [BOI2003]团伙(并查集)
    超有爱的并查集[转]
    [ZJOI2006]三色二叉树 (树形dp)
  • 原文地址:https://www.cnblogs.com/little-YTMM/p/5397186.html
Copyright © 2011-2022 走看看