注解是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继承关系的地方,该注解也能被继承过来.这个可能不好理解.下面的代码加以说明.
1
2
3
4
5
6
|
@Retention (RetentionPolicy.RUNTIME)
@Target ({ElementType.TYPE,ElementType.METHOD})
@Inherited
public @interface AnnoInherited {
}
|
测试代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
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能继承过来.
自定义注解:
自定义注解的实例如下.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
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 ;
}
|
测试代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
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{
}
|
控制台输出:
1
2
3
4
5
|
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通过动态代理技术生成的.这也揭示了注解特性的底层实现原理.关于注解的具体底层技术原理,这里不再详谈.
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。