苏黎 搜索开发工程师

Java注解的学习和总结

2018-04-22
suli

Java注解的学习和总结

以前没写过多少java对java的注解模式很好奇,今天就凑空研究一下看一下。

1. Java元注解

元注解包括四种@Retention @Target @Document @Inherited这四种注解。

  1. Annotation型定义为@interface, 所有的Annotation会自动继承java.lang.Annotation这一接口,并且不能再去继承别的类或是接口。
  2. 参数成员只能用public或者default这两种访问权限修饰。
  3. 参数成员只能用byte、String等基础类型。
  4. 要获取类方法和字段的注解信息,必须通过Java的反射技术来获取Annotation对象,因为你除此之外没有别的获取注解对象的方法。

自定义注解类的时候可以指定目标(类、方法、字段, 构造函数等)、注册的生命周期,是否将注解包含javadoc中及是否允许子类继承父类中的注解, 具体如下:

  1. @Target 表示该注解目标,可能的 ElemenetType 参数包括:
      ElemenetType.CONSTRUCTOR 构造器声明
      ElemenetType.FIELD 域声明(包括 enum 实例) 
      ElemenetType.LOCAL_VARIABLE 局部变量声明 
      ElemenetType.METHOD 方法声明 
      ElemenetType.PACKAGE 包声明 
      ElemenetType.PARAMETER 参数声明 
      ElemenetType.TYPE 接口(包括注解类型)或enum声明
    
  2. @Retention 表示该注解的生命周期,可选的 RetentionPolicy 参数包括:
  RetentionPolicy.SOURCE 注解将被编译器丢弃 
  RetentionPolicy.CLASS 注解在class文件中可用但会被VM丢弃 
  RetentionPolicy.RUNTIME VM将在运行期也保留注释因此可以通过反射机制读取注解的信息
  1. @Documented 指示将此注解包含在 javadoc 中.
  2. @Inherited 指示允许子类继承父类中的注解.

2.类注解

注解实例

@MyAnnotation(name="someName",  value = "Hello World")
public class TheClass {
}

上面就是实际中使用注解的例子。

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)

public @interface MyAnnotation {
  public String name();
  public String value();
}

上面是一个定义注解的例子。 下面是使用一个注解:

Class aClass = TheClass.class;
Annotation[] annotations = aClass.getAnnotations();

for(Annotation annotation : annotations){
    if(annotation instanceof MyAnnotation){
        MyAnnotation myAnnotation = (MyAnnotation) annotation;
        System.out.println("name: " + myAnnotation.name());
        System.out.println("value: " + myAnnotation.value());
    }
}

另外一种使用方法:

Class aClass = TheClass.class;
Annotation annotation = aClass.getAnnotation(MyAnnotation.class);

if(annotation instanceof MyAnnotation){
    MyAnnotation myAnnotation = (MyAnnotation) annotation;
    System.out.println("name: " + myAnnotation.name());
    System.out.println("value: " + myAnnotation.value());
}

3. 方法注解

方法注解

public class TheClass {
  @MyAnnotation(name="someName",  value = "Hello World")
  public void doSomething(){}
}

可以用下面的方法来使用:

Method method = ... // 获取方法对象
Annotation annotation = method.getAnnotation(MyAnnotation.class);

if(annotation instanceof MyAnnotation){
    MyAnnotation myAnnotation = (MyAnnotation) annotation;
    System.out.println("name: " + myAnnotation.name());
    System.out.println("value: " + myAnnotation.value());
}

4. 参数注解

也可以使用参数注解

public class TheClass {
  public static void doSomethingElse(
        @MyAnnotation(name="aName", value="aValue") String parameter){
  }
}

下面是注解模式的应用

Method method = ... //获取方法对象
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
Class[] parameterTypes = method.getParameterTypes();

int i=0;
for(Annotation[] annotations : parameterAnnotations){
  Class parameterType = parameterTypes[i++];

  for(Annotation annotation : annotations){
    if(annotation instanceof MyAnnotation){
        MyAnnotation myAnnotation = (MyAnnotation) annotation;
        System.out.println("param: " + parameterType.getName());
        System.out.println("name : " + myAnnotation.name());
        System.out.println("value: " + myAnnotation.value());
    }
  }
}

5. 变量注解

变量注解例子:

public class TheClass {

  @MyAnnotation(name="someName",  value = "Hello World")
  public String myField = null;
}

访问指定变量的注解:

Field field = ... //获取方法对象
Annotation[] annotations = field.getDeclaredAnnotations();

for(Annotation annotation : annotations){
 if(annotation instanceof MyAnnotation){
 MyAnnotation myAnnotation = (MyAnnotation) annotation;
 System.out.println("name: " + myAnnotation.name());
 System.out.println("value: " + myAnnotation.value());
 }
}

总结

注解可以在运行时候使用java的反射来进行动态的处理,也可以在java编译阶段进行处理。


上一篇 gcc 特性学习

下一篇 MurmurHash算法

Comments

Content