欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

深入理解Java注解的使用方法

程序员文章站 2023-01-07 16:19:42
注解是jdk1.5新增的特性.大家都知道,jdk1.5在java的发展史上有着划时代的意义.而注解的出现,在某种程度上颠覆了框架的设计.比如,spring在注解出现后,改善...

注解是jdk1.5新增的特性.大家都知道,jdk1.5在java的发展史上有着划时代的意义.而注解的出现,在某种程度上颠覆了框架的设计.比如,spring在注解出现后,改善了原先五大组件的模式,增加了基于注解的实现方式.现在重点讲讲注解的使用.

元注解:

      jdk1.5定义了4个元注解,元注解的作用是注解其他的注解.

       1.@retention

       2.@target

       3.@documented

       4.@inherited

       @retention用于指明该注解存在的时机.参数有三个值可选:retentionpolicy.source,retentionpolicy.class,retentionpolicy.runtime可供选择.分别表示:源码中保留注解,字节码文件中保留注解,运行时保留注解.

       @target用于指明注解能作用的范围.比如参数中设置为elementtype.type,表示作用于类和接口.如果你用来注解方法,则会发生编译错误.由此可见它的功能是通过编译器实现的.

       @documented表明该注解在使用javadoc工具生成开发文档时,也会被纳入进去.

       @inherited表明,某个位置使用该注解,那么在存在java继承关系的地方,该注解也能被继承过来.这个可能不好理解.下面的代码加以说明.     

@retention(retentionpolicy.runtime)
@target({elementtype.type,elementtype.method})
@inherited
public @interface annoinherited {
  
}


测试代码:

public class testannoinherated {
  public static void main(string[] args) {
    annotation[] annos=new goo().getclass().getannotations();
    for(annotation a:annos){
      system.out.println(a);
    }
  }
}

@annoinherited
class foo{
  
}

class goo extends foo{
  
}  

控制台输出:

@test.annotation.annoinherited()

上例中goo前面并没有加注解@annoinherited,但是父类foo前面有,而@annoinherited加了元注解@inherited,所以foo能继承过来.

自定义注解:

自定义注解的实例如下.

package test.annotation;

import java.lang.annotation.documented;
import java.lang.annotation.elementtype;
import java.lang.annotation.retention;
import java.lang.annotation.retentionpolicy;
import java.lang.annotation.target;

@target(elementtype.type)
@retention(retentionpolicy.runtime)
@documented
public @interface animalinfo {
  string shout() default "";
  
  //能不能看门
  boolean isguard() default true;
}

测试代码:

public class testanimalinfo {
  public static void main(string[] args) {
    animal animal=new animal();
    animalinfo info=animal.getclass().getannotation(animalinfo.class);
    if(info!=null){
      annotation anno=info;//此处并没有报错.annotation是一个接口.info是一个注解.这是因为编译器会将注解编译成接口,并且继承了annotation
      system.out.println("annotation类信息:"+annotation.class);
      system.out.println("animalinfo类信息:"+animalinfo.class);
      class[] cs=animalinfo.class.getinterfaces();
      for(class c:cs){
        system.out.println(c); //animalinfo编译后就是一个接口,并且继承了annotation,这里得到了证实.
      }
      system.out.println("info对象的类信息:"+info.getclass());
      if("wangwang".equals(info.shout())&&info.isguard()){
        system.out.println("the animal is a dog");
      }else if("miaomiao".equals(info.shout())&&!info.isguard()){
        system.out.println("the animal is a cat");
      }else{
        system.out.println("the animal is not a dog or cat");
      }
    }else{
      system.out.println("it's not a animal");
    }
  }
}

@animalinfo(shout="wangwang",isguard=true)
class animal{
  
}

控制台输出:

annotation类信息:interface java.lang.annotation.annotation
animalinfo类信息:interface test.annotation.animalinfo
interface java.lang.annotation.annotation
info对象的类信息:class com.sun.proxy.$proxy1
the animal is a dog

代码分析:从控制台可以看到.@animalinfo注解其实编译后就是接口,并且它继承了annnotation.而通过反射获得的注解实例,名字为$proxy1,是一个类的对象.可见,该注解实例是jvm通过动态代理技术生成的.这也揭示了注解特性的底层实现原理.关于注解的具体底层技术原理,这里不再详谈.

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。