Java 注解 Anonotation
1、什么是注解
Annotation表示一种注释的语法,在Java中最早提倡的是程序与配置相分离,而最新的理论是把所有配置直接写入到代码中,如果想完成这样的功能,则使用Annotation。
?
2、系统内建的Annotation
?
2.1??@Override
重写父类的方法
?
2.2??@Deprecated
表示不建议使用的操作,如果使用该操作也不报错,只是在编辑器中出现横线警告信息,不建议使用。如Date对像中的很多方法。
@Deprecated
public?int?getDay()?{
????return?normalize().getDayOfWeek()?-?gcal.SUNDAY;
}
?
2.3??@SuppressWaring表示压制警告,如果出现警告信息,则可以压制不提示。@SuppressWaring的属性String[]?value()为数组,说明可以同时压制多个警告。
@Target({TYPE,?FIELD,?METHOD,?PARAMETER,?CONSTRUCTOR,?LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public?@interface?SuppressWarnings?{
????String[]?value();
}
?
3、自定义Annotation
?
3.1?语法
public?@interface?名称{
}
3.2?定义MyAnnotaion
package?com.chenzehe.annotation;
??? public?@interface?MyAnnotation?{
}
如果要使用此Annotation,则使用@符访问,不在同一个包中需要导入。如下面Info类的使用:
package?com.chenzehe.annotation;
@MyAnnotation
public?class?Info?{
}
3.3?Annotation的属性定义
Annotation的属性定义以()结尾。
package?com.chenzehe.annotation;
public?@interface?MyAnnotation?{
????public?String?key();
????public?String?value();
}
上面Annotation定义了两个变量key和value,如果要使用此Annotation,则必须明确的给出其内容。如:
package?com.chenzehe.annotation;
@MyAnnotation(key="name",value="chenzehe")
public?class?Info?{
}
?
如果想给Annotation的变量设置默认值,则使用default关键字完成,如:
package?com.chenzehe.annotation;
public?@interface?MyAnnotation?{
? public?String?key()?default?"name";
??? public?String?value()?default?"chenzehe";
}
使用此Annotation时,可以不用显示的设置变量值,而使用默认值。
3.4?Annotation中的属性值可以通过枚举限制
定义枚举类型Color:
package?com.chenzehe.annotation;
public?enum?Color?{
????RED,GLREN,BLUE;
}
在MyAnnotation中定义一个Color类型的变量:
package?com.chenzehe.annotation;
public?@interface?MyAnnotation?{
????public?Color?color()?default?Color.RED;
}
则使用MyAnnotation中的color变量时,值只能取Color中定义的类型:
package?com.chenzehe.annotation;
@MyAnnotation(color="red")
public?class?Info?{
}
上面给变量color赋值出错,正确如下:
package?com.chenzehe.annotation;
@MyAnnotation(color?=?Color.RED)
public?class?Info?{
}
3.5?Annotation中的属性为数组类型
如果Annotation中的属性为数组类型,则使用的时候必须按照数组的方式操作。
package?com.chenzehe.annotation;
public?@interface?MyAnnotation?{
public?String[]?urls();
}
使用:
package?com.chenzehe.annotation;
@MyAnnotation(urls?=?{?"www.baidu.com",?"g.cn"?})
public?class?Info?{
}
4、注释类型?Retention和枚举?RetentionPolicy
@Documented
@Retention(value=RUNTIME)
@Target(value=ANNOTATION_TYPE)
public?@interface?Retention
????? 指示注解类型的注释要保留多久,也就是作用范围。如果注释类型声明中不存在?Retention?注释,则保留策略默认为?RetentionPolicy.CLASS。只有元注释类型直接用于注释时,Target?元注释才有效。如果元注释类型用作另一种注释类型的成员,则无效。
枚举?RetentionPolicy定义了三种Annotation的范围:
CLASS?在编译之后的class文件中作用
RUNTIME?在运行的时候起作用
SOURCE?只在源代码中起作用
系统内置的三个Annotation的作用域分别为:
@Override:@Retention(value=SOURCE)源码
@Deprecated:@Retention(value=RUNTIME)运行时
@SuppressWarnings:@Retention(value=SOURCE)源码
?
5、反射与Annotation
一个Annotation如果要想起作用,则肯定要依赖反射机制,通过反射可以取得一个方法上声明的?Annotation全部内容。任何一下自定义的Annotation都是继承了java.lang.annotation.Annotation接口。
在Field?Method?Constructor?的父类AccessibleObject??定义了如下与Annotation操作相关的方法:
取得全部Annotation?:public?Annotation[]?getAnnotations()??
判断操作的是否是指定的Annotation:public?boolean?isAnnotationPresent(Class<??extends?Annotation>?annotationClass)?
例:下面Info类中toString()方法使用的Annotation,在Test类中用反射访问这些Annotation
package?com.chenzehe.annotation;
public?class?Info?{
????@Override
????@Deprecated
????@SuppressWarnings(value?=?"")
????public?String?toString()?{
????????return?"Hello?World!";
????}
}
?
package?com.chenzehe.annotation;
import?java.lang.annotation.Annotation;
import?java.lang.reflect.Method;
public?class?Test?{
????public?static?void?main(String[]?args)?throws?Exception?{
????????Class<?>?cls?=?Class.forName("com.chenzehe.annotation.Info");
????????Method?method?=?cls.getMethod("toString");
????????Annotation[]?annotations?=?method.getAnnotations();
????????for?(int?i?=?0;?i?<?annotations.length;?i++)?{
????????????System.out.println(annotations[i]);
????????}
????}
}
输出:@java.lang.Deprecated(),而Info类中使用的三个Annotation中,只有Deprecated的范围为runtime,说明只有范围在runtime的才能被找到。
?
把MyAnnotation类改成runtime范围,并在Test类中用反射取得他的属性:
package?com.chenzehe.annotation;
import?java.lang.annotation.Retention;
import?java.lang.annotation.RetentionPolicy;
@Retention(value?=?RetentionPolicy.RUNTIME)
public?@interface?MyAnnotation?{
????public?String?key()?default?"name";
????public?String?value();
}
在Info中使用该Annotation:
package?com.chenzehe.annotation;
public?class?Info?{
????@Override
????@Deprecated
????@SuppressWarnings(value?=?"")
????@MyAnnotation(value="chenzehe")
????public?String?toString()?{
????????return?"Hello?World!";
????}
}
在Test类中使用反射取得其属性:
package?com.chenzehe.annotation;
import?java.lang.annotation.Annotation;
import?java.lang.reflect.Method;
public?class?Test?{
???? public?static?void?main(String[]?args)?throws?Exception?{
???????? Class<?>?cls?=?Class.forName("com.chenzehe.annotation.Info");
???????? Method?method?=?cls.getMethod("toString");
???????? Annotation[]?annotations?=?method.getAnnotations();
???????? for?(int?i?=?0;?i?<?annotations.length;?i++)?{
???????????? if?(method.isAnnotationPresent(MyAnnotation.class))?{
???????????????? MyAnnotation?myAnnotation?=?method.getAnnotation(MyAnnotation.class);
???????????????? String?key?=?myAnnotation.key();
???????????????? String?value?=?myAnnotation.value();
???????????????? System.out.println(key?+?":"?+?value);
???????????? }
???????? }
????}
}
?
6、Target
在java.lang.annotation中已定义的注解类型Target?,用于指定所定义的注解使用的范围为方法、类、属性等。
默认情况下一个自定义的Annotation可以在任意地方使用,如自定义的MyAnnotation,如果没有指定Target,则可以在任意地方使用:
package?com.chenzehe.annotation;
@MyAnnotation()
public?class?Info?{
????@MyAnnotation()
????private?Stringname;
????@MyAnnotation()
????public?String?toString()?{
????????return?"Hello?World!";
????}
}
在Target的定义中,value的属性类型为?ElementType[],所指定的范围有以下八种:
1、只能在Annotation中出现:ANNOTATION_TYPE?
2、只能在构造方法中出现:CONSTRUCTOR?
3、在属性中出现:FIELD?
4、只能在本地变量中出现:LOCAL_VARIABLE?
5、在方法上出现:METHOD?
6、在包声明中出现:PACKAGE?
7、在参数声明中出现:PARAMETER?
8、类、接口(包括注释类型)或枚举声明中使用:?TYPE?
如以下自定义的MyAnnotation只能在方法中使用:
package?com.chenzehe.annotation;
import?java.lang.annotation.ElementType;
import?java.lang.annotation.Retention;
import?java.lang.annotation.RetentionPolicy;
import?java.lang.annotation.Target;
@Retention(value?=?RetentionPolicy.RUNTIME)
@Target(value=(ElementType.METHOD))
public?@interface?MyAnnotation?{
??? public?String?key()?default?"name";
??? public?String?value()?default?"chenzehe";
}
Target中的属性value定义为数组类型,所以可以同时设置多个ElementType,如:
@Target(value?=?{?ElementType.METHOD,?ElementType.FIELD?})
?
7、Document注解
在java.lang.annotation中定义的注解类型Documented?,指示某一类型的注释将通过?javadoc?和类似的默认工具进行文档化。应使用此类型来注释这些类型的声明:其注释会影响由其客户端注释的元素的使用。如果类型声明是用?Documented?来注释的,则其注释将成为注释元素的公共?API?的一部分。?
如声明MyAnnotation注解:
package?com.chenzehe.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;
@Documented
@Retention(value?=?RetentionPolicy.RUNTIME)
@Target(value?=?{?ElementType.METHOD,?ElementType.FIELD?})
public?@interface?MyAnnotation?{
????public?String?key()?default?"name";
????public?String?value()?default?"chenzehe";
}
在Info类中使用:
package?com.chenzehe.annotation;
public?class?Info?{
????/**
? ?? *?此方法是覆盖Object中的toString()方法
? ?? */
????@MyAnnotation()
????public?String?toString()?{
????????return?"Hello?World!";
????}
}
可以通过eclipse的export导出javadoc,在其注释中能看到上面编写的注释
?
8、Inherited
在java.lang.annotation中声明Inherited?,表示该annotation是否被该子类断承下去,如果没有此注解,说明不能被断承。
如自定义的MyAnnotation,加入@Inherited,说明此Annotation可以被子类断承:
package?com.chenzehe.annotation;
import?java.lang.annotation.Inherited;
import?java.lang.annotation.Retention;
import?java.lang.annotation.RetentionPolicy;
@Inherited
@Retention(value?=?RetentionPolicy.RUNTIME)
public?@interface?MyAnnotation?{
???public?String?key()?default?"name";
????public?String?value()?default?"chenzehe";
}
在Info类中使用该Annotation:
package?com.chenzehe.annotation;
@MyAnnotation
public?class?Info?{
}
创建Info类的子类PersonInfo:
package?com.chenzehe.annotation;
public?class?PersonInfo?extends?Info?{
}
使用反射取得PersonInfo类的annotation信息:
package?com.chenzehe.annotation;
import?java.lang.annotation.Annotation;
public?class?Test?{
????public?static?void?main(String[]?args)?throws?Exception?{
????????Class<?>?cls?=?Class.forName("com.chenzehe.annotation.PersonInfo");
????????Annotation[]?annotations?=?cls.getAnnotations();
????????for?(int?i?=?0;?i?<?annotations.length;?i++)?{
????????????System.out.println(annotations[i]);
????????}
????}
}
如果MyAnnotation中加入@Inherited,则可以取到MyAnnotaion信息,如果没有加则取不到。
?