• java注解的使用


    java中注解的使用

    1.说再前面

    使用注解开发的好处

    1.使代码更加干净易读,易于维护修改。比如,以前使用spring的开发,都是基于xml文件实现了统一的配置管理,但是缺点也是显而易见的,就是随着项目的越来越大,xml文件会变得越来越复杂,维护成本也会越来越高。使用注解就可以提供更大的便捷性,易于维护修改。

    2 可以实现代码的类型检查,特别是在编译器的角度实现一些类型检查,比如预检查(@Override)和抑制警告(@SuppressWarnings)等。

    3 自定义注解,作为额外信息的载体,存储有关程序的额外信息

    2 注解的分类以及使用

    ​ Java注解是附加在代码中的一些元信息,用于编译和运行时进行解析和使用,起到说明、配置的功能。

    注解不会影响代码的实际逻辑,仅仅起到辅助性的作用。包含在java.lang.annotation包中。注解的定义类似于接口的定义,使用@interface来定义,定义一个方法即为注解类型定义了一个元素,方法的声明不允许有参数或throw语句,返回值类型被限定为原始数据类型、字符串String、Class、enums、注解类型,或前面这些的数组,方法可以有默认值。注解并不直接影响代码的语义,但是他可以被看做是程序的工具或者类库。它会反过来对正在运行的程序语义有所影响。注解可以从源文件、class文件或者在运行时通过反射机制多种方式被读取。

    一般来说,注解一般分为三种类型: 元注解,标准注解,自定义注解

    2.1 元注解

    元注解是专职负责注解其他注解,主要是标明该注解的使用范围,生效范围。我们是不能改变它的,只能用它来定义我们自定义的注解。

    包括 @Retention @Target @Document @Inherited四种。(java.lang.annotation中提供,为注释类型)。

    注解 说明
    @Target 定义注解的作用目标,也就是可以定义注解具体作用在类上,方法上,还是变量上
    @Retention 定义注解的保留策略。RetentionPolicy.SOURCE:注解仅存在于源码中,在class字节码文件中不包含;RetentionPolicy.CLASS:默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得;RetentionPolicy.RUNTIME:注解会在class字节码文件中存在,在运行时可以通过反射获取到。
    @Document 说明该注解将被包含在javadoc中
    @Inherited 说明子类可以继承父类中的该注解

    Target类型主要依赖于ElementType这个类型,具体的类型如下:

    Target类型 说明
    ElementType.TYPE 接口、类、枚举、注解
    ElementType.FIELD 字段、枚举的常量
    ElementType.METHOD 方法
    ElementType.PARAMETER 方法参数
    ElementType.CONSTRUCTOR 构造函数
    ElementType.LOCAL_VARIABLE 局部变量
    ElementType.ANNOTATION_TYPE 注解
    ElementType.PACKAGE

    2.2 标准注解

    Java标准注解提供了三个,定义在java.lang中的注解,我认为这三个注解的作用更多的是一种注释

    • @Override 表示当前方法覆盖父类中的方法。

    • @Deprecated 标记一个元素为已过期,避免使用

    支持的元素类型为:CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE

    • @SuppressWarnings 不输出对应的编译警告

      一个简单的使用demo:

      @SuppressWarnings(value = {"unused", "rawtypes"})
      public class Children  extends Parent{
          @Override
          public void work() {
              System.out.println("我是一个被重写的方法");
          }
      
          @Deprecated
          public void play(){
              System.out.println("这个方法不推荐使用了");
          }
      }
      

    2.3 自定义注解实现一个sql语句的拼接

    需要注意的方面:注解的定义类似于接口的定义,使用@interface来定义,定义一个方法即为注解类型定义了一个元素,方法的声明不允许有参数或throw语句,返回值类型被限定为原始数据类型、字符串String、Class、enums、注解类型,或前面这些的数组,方法可以有默认值。

    自定义注解一般可以分为三步: 定义注解,使用注解,读取注解

    定义注解

    @Target(ElementType.TYPE) //注解加载类上
    @Retention(RetentionPolicy.RUNTIME) // 运行时读取注解
    
    public @interface Table {
        String value(); 
    }
    
    
    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    public@interface UserFiled {
        String name();
        String type();
        int length();
    }
    

    使用注解

    // 将自定义的注解加在用户上,实现一个表的映射
    @Table(value = "user_table")
    public class User {
    
        @UserFiled(name = "user_id",type = "int",length = 8)
        private int userId;
    
        @UserFiled(name = "user_name",type = "varchar",length = 16)
        private String userName;
    
        @UserFiled(name = "password",type = "varchar",length = 16)
        private String password;
    
        public int getUserId() {
            return userId;
        }
    
        public void setUserId(int userId) {
            this.userId = userId;
        }
    
        public String getUserName() {
            return userName;
        }
    
        public void setUserName(String userName) {
            this.userName = userName;
        }
    
        public String getPassword() {
            return password;
        }
    
        public void setPassword(String password) {
            this.password = password;
        }
    }
    
    

    读取注解的内容

    /**
     * 读取注解中的值
     */
    public class GetUser {
        public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
            Class userClass = Class.forName("annocation.blog.User");
    
            // 读取类上的注解
            Table table = (Table) userClass.getAnnotation(Table.class);
            System.out.println(table.value());
    
            // 读取属性上注解
            Field userId = userClass.getDeclaredField("userId");
            UserFiled userFiledId = userId.getAnnotation(UserFiled.class);
            System.out.println(userFiledId.length() + "----" + userFiledId.type() + "-----" + userFiledId.name());
    
            Field userName = userClass.getDeclaredField("userName");
            UserFiled userFiledName = userName.getAnnotation(UserFiled.class);
            System.out.println(userFiledName.length()+"----"+userFiledName.type()+"----"+userFiledName.name());
    
            Field password = userClass.getDeclaredField("password");
            UserFiled userFiledPassword = password.getAnnotation(UserFiled.class);
            System.out.println(userFiledPassword.name() + "-----" + userFiledPassword.type() + "-----" + userFiledPassword.length());
    
            // 拼接一个sql语句
            String name = "chenwei";
            String sql ="select * from" + table.value()+"where"+userFiledName.name()+"="+name;
        }
    }
    
    

    结果:

    user_table
    user_id----int-----8
    user_name----varchar----16
    password-----varchar-----16
    

    自定义注解的实现过程:

    1,定义注解

    2,使用注解,根据自己定义的注解来达到一些目的,本例中,就是使用注解来完成数据库表和实体类的映射关系

    3 读取注解的内容,也是比较重要的一部分,核心还是利用了反射的思想,得到使用注解的这个类,根据类中的getAnnotion的方法得到定义的注解,获得注解上的值。

    3 注解的实现的原理

    注解的实现的原理很大的一部分是基于反射实现。

    ​ 反射可以获取到Class对象,进而获取到Constructor、Field、Method等实例,点开源码结构发现Class、Constructor、Field、Method等均实现了AnnotatedElement接口,AnnotatedElement接口的方法如下

    // 判断该元素是否包含指定注解,包含则返回true
    boolean isAnnotationPresent(Class<? extends Annotation> annotationClass)
        
    // 返回该元素上对应的注解,如果没有返回null
    <T extends Annotation> T getAnnotation(Class<T> annotationClass);
    
    // 返回该元素上的所有注解,如果没有任何注解则返回一个空数组
    Annotation[] getAnnotations();
    
    // 返回指定类型的注解,如果没有返回空数组
    T[] getAnnotationsByType(Class<T> annotationClass)
        
    // 返回指定类型的注解,如果没有返回空数组,只包含直接标注的注解,不包含inherited的注解
    T getDeclaredAnnotation(Class<T> annotationClass)
        
    // 返回指定类型的注解,如果没有返回空数组,只包含直接标注的注解,不包含inherited的注解
    T[] getDeclaredAnnotationsByType
        
    // 返回该元素上的所有注解,如果没有任何注解则返回一个空数组,只包含直接标注的注解,不包含inherited的注解
    Annotation[] getDeclaredAnnotations();
    

    通过一个实例再次说明一下注解的使用过程:

    定义注解

    @Documented
    @Target({ElementType.TYPE, ElementType.FIELD,ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface MyAnnotaion {
        String getValue() default "this is myAnntaion";
        int order() default 0;
    }
    

    使用注解

    @MyAnnotaion(getValue = "annotation on class")
    public class Demo {
    
        @MyAnnotaion(getValue = "annotation on filed")
        public String name;
    
        @MyAnnotaion(getValue = "annotation on method")
        public void hello(){
        }
    
        @MyAnnotaion
        public void defaultMethod(){
    
        }
    }
    
    

    利用反射读取注解中的值。

    public class TestDemo {
        public static void main(String[] args) throws NoSuchFieldException, NoSuchMethodException {
            /**
             * 获取类上的注解
             */
            Class<Demo> demoClass = Demo.class;
            Annotation[] annotaion = demoClass.getAnnotations();
            printAnnotation(annotaion);
    
            /**
             * 读取成员变量上的注解
             */
            Field name = demoClass.getField("name");
            Annotation[] getOnFiled = name.getAnnotations();
            printAnnotation(getOnFiled);
    
            /**
             * 读取方法上的注解
             */
            Method hello = demoClass.getMethod("hello", null);
            MyAnnotaion onMethod = hello.getAnnotation(MyAnnotaion.class);
            System.out.println(onMethod.getValue());
    
            /**
             * 获取默认方法上的注解
             */
            Method defaultMethod = demoClass.getMethod("defaultMethod", null);
            MyAnnotaion onDefaultMethod = defaultMethod.getAnnotation(MyAnnotaion.class);
            System.out.println(onDefaultMethod.getValue());
    
        }
    
        public static void printAnnotation(Annotation... annotations) {
            for (Annotation annotation : annotations) {
                System.out.println(annotation);
            }
        }
    }
    
    

    运行结果

    @annocation.MyAnnotaion(getValue=annotation on class, order=0)
    @annocation.MyAnnotaion(getValue=annotation on filed, order=0)
    annotation on method
    this is myAnntaion
    

    参考资料:

    http://blog.kimzing.com/java/Java注解入门到精通-学这一篇就够了/

    《java编程思想》

  • 相关阅读:
    如何评测软件工程知识技能水平?
    创新产品的需求分析:未来的图书会是什么样子?
    案例分析:设计模式与代码的结构特性
    业务领域建模Domain Modeling
    转载:10 Easy Steps to a Complete Understanding of SQL
    二十六个月Android学习工作总结
    android sdk无法更新问题解决
    android中利用view画出一条竖线
    android-Java SoftReference,WeakReference,Direct Reference简介
    Intellij IDEA开发第一个android应用教程
  • 原文地址:https://www.cnblogs.com/chentang/p/13959831.html
Copyright © 2020-2023  润新知