zoukankan      html  css  js  c++  java
  • java中注解的使用

           使用过ssh框架的人一定也使用过注解,尤其是在spring框架中,注解可谓是spring容器和AOP编程的重要环节。注解就是用于修饰类、全局变量、方法、参数或局部变量的接口,java中规定,注解的使用不允许影响其修饰类的存在,也就是说如果将一个类的注解全部删除,这个类也能够编译通过。java中,注解的应用主要有四个方面:类注解,全局变量注解,方法注解,参数注解。其他的还有诸如包注解和局部变量注解这里暂不作讨论。首先我们定义一个类注解如下:

    package annotation;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE)
    public @interface TypeAnnotation {
      String say() default "this is a type annotation";
    }
    

            在java中有四个元注解,分别是@RetentIon、@Target、@Inherited和@Document,@Retention指定的是注解的生命周期,其value参数的值有三个:RUNTIME、SOURCE、CLASS。RUNTIME表示当前修饰的注解是在虚拟机运行时实时加载的,也就是虚拟机中要用到该注解一次就加载一次;CLASS表示该注解在类的源文件和编译后的class文件中都存在,而在类加载器加载到虚拟机中时就会消失,SOURCE表示该注解只在源文件中存在,当编译成class文件后就不存在了。@Target指定的是当前注解可修饰的类型,可value参数可取如下几个值:Type、FIELD、METHOD、PARAMETER、PACKAGE、CONSTRUCTOR、LOCAL_VARIABLE、ANNOTATION_TYPE等。其中最主要的应用有TYPE、FIELD、METHOD、PARAMETER,其分别表示类注解,全局变量注解,方法注解,参数注解,其余几个则表示包注解,构造器注解,局部变量注解,用于注解的注解等。

           注解的声明同接口的声明类似,不过要在interface关键字前加@修饰以标明其为一个注解,在使用注解是括号中的变量名称也即注解声明时方法名称,声明方法时可以默认指定该方法的默认值,即在使用注解时若不指定该“变量”则该“变量”使用该方法的默认值,这里需要说明的是,若方法名称为value,那么在使用注解时,注解中该“变量名”可以不写,如上述Retention注解中的值(这种写法要求使用该注解时只指定这一个方“变量”的值)。

           如下示例我们分别演示了四个常用注解的声明方式:

    package annotation;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.FIELD)
    public @interface FieldAnnotation {
      String say() default "this is a field annotation";
    }
    
    package annotation;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    public @interface MethodAnnotation {
      String say() default "this is a method annotation";
    }
    
    package annotation;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.PARAMETER)
    public @interface ParamAnnotation {
      String say() default "this is a parameter annotation";
    }
    

            由于注解的使用已经非常广泛,下面我们通过一个类来简单演示注解的使用:

    package source;
    
    import annotation.FieldAnnotation;
    import annotation.MethodAnnotation;
    import annotation.ParamAnnotation;
    import annotation.TypeAnnotation;
    
    @TypeAnnotation(say = "this is modified type annotation")
    public class Apple {
      @FieldAnnotation(say = "this is modified field annotation")
      private String color;
    
      @MethodAnnotation(say = "this is modified method annotation")
      public void setColor(@ParamAnnotation String color) {
        this.color = color;
      }
    
      public String getColor() {
        return color;
      }
    }
    

            由于java规定,注解的使用不能对其使用类的存在产生影响,因而注解对于使用类只能起到一定的辅助作用,一个非常好的应用实例为javaweb中的权限控制,我们可以预定义一些权限码,然后在需要权限校验的地方使用自定义的注解;不过,因为java支持反射,因而通过反射注解就可以与使用类非常好的配合在一起,从而实现某些功能,一个非常好的例子是spring中的实体类对象属性的注入。下面我们通过一个简单的例子来说明如何通过反射获取注解值,并且利用反射使其与使用类产生关系:

    package test;
    
    import annotation.FieldAnnotation;
    import annotation.MethodAnnotation;
    import annotation.ParamAnnotation;
    import annotation.TypeAnnotation;
    import source.Apple;
    
    import java.lang.annotation.Annotation;
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    import java.lang.reflect.Parameter;
    import java.lang.reflect.Type;
    
    import org.junit.Test;
    
    public class App {
    
      @Test
      public void testApp() throws Exception {
    
        Apple apple = Apple.class.newInstance();
    
        // 获取被注释的类
        if (Apple.class.isAnnotationPresent(TypeAnnotation.class)) {
          System.out.println(Apple.class.getAnnotation(TypeAnnotation.class).say());
        }
    
        // 获取被注释的变量
        Field[] fields = Apple.class.getDeclaredFields();
        for (Field f : fields) {
          if (f.isAnnotationPresent(FieldAnnotation.class)) {
            System.out.println(f.getAnnotation(FieldAnnotation.class).say());
          }
        }
    
        // 获取被注释的方法
        Method[] methods = Apple.class.getDeclaredMethods();
        for (Method m : methods) {
          if (m.isAnnotationPresent(MethodAnnotation.class)) {
            System.out.println(m.getAnnotation(MethodAnnotation.class).say());
          }
    
          // 获取当前方法被注释的参数
          Parameter[] parameters = m.getParameters();
          for (Parameter p : parameters) {
            if (p.isAnnotationPresent(ParamAnnotation.class)) {
              System.out.println(p.getAnnotation(ParamAnnotation.class).say());
            }
          }
    
          // 通过反射调用方法
          if (m.getName().startsWith("set")) {
            m.invoke(apple, "Red");
          }
        }
    
        System.out.println("通过反射调用对象的方法后对象变量的值:" + apple.getColor());
      }
    }
    

           运行结果如下:

    this is modified type annotation
    this is modified field annotation
    this is modified method annotation
    this is a parameter annotation
    通过反射调用对象的方法后对象变量的值:Red

           上述示例简单的阐述了反射和注解之间紧密的联系。在实际应用中, 注解的使用非常广泛,通过注解可以大大简化我们的开发,并且实现某些特定的效果,本文对注解的创建,使用以及深层调用方式进行了简单的介绍,希望大家能够喜欢!

  • 相关阅读:
    Android之TabHost使用(引用SDK例子文档)
    Android之在线词典
    校验插入指定结点是否导致编码循环的示例函数
    查表法按日期生成流水号的示例.sql
    备份数据库并提供下载的asp文件
    Metro风格XAML应用程序性能技巧
    导入文本文件时如何指定字段类型.sql
    宝塔形数据的处理.sql
    将某个目录上的Excel表,导入到数据库中.sql
    Using SqlDataReader’s new async methods in .Net 4.5 Beta
  • 原文地址:https://www.cnblogs.com/zhangxufeng/p/8284069.html
Copyright © 2011-2022 走看看