发一下牢骚和主题无关:
package anno;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
String value();
}
package anno;
import java.lang.annotation.Annotation;
@MyAnnotation("sss")
public class AnnotationTest {
public static void main(String[] args) {
Annotation[] annotations = AnnotationTest.class.getAnnotations();
System.out.println(((MyAnnotation)annotations[0]).value());
}
}
打印:sss
一、java内置注解
- J0 y. E* ?9 c1 C6 R' t5 Z& l
0 E( x( H$ S+ Y* @
1、@Target 表现该注解用于什么地方,可能的 ElemenetType 参数含包:
ElemenetType.CONSTRUCTOR 构造器声明
/ ^& b9 Z* h. g& Y, t- A+ Y7 [9 \
ElemenetType.FIELD 域声明(含包 enum 实例)
ElemenetType.LOCAL_VARIABLE 局部量变声明
5 O! ?- S3 S0 y" G) z
ElemenetType.METHOD 方法声明
! V! b. V4 f5 X' a/ c, b, ?+ W1 K/ g
ElemenetType.PACKAGE 包声明
2 S' f+ P ?* c+ X
ElemenetType.PARAMETER 参数声明
6 s! Q9 J& @! x
ElemenetType.TYPE 类,接口(含包注解型类)或enum声明
2、@Retention 表现在什么级别保存该注解信息。可选的 RetentionPolicy 参数含包:
RetentionPolicy.SOURCE 注解将被编译器抛弃
4 P' T+ s1 {9 }
RetentionPolicy.CLASS 注解在class文件中可用,但会被VM抛弃
RetentionPolicy.RUNTIME VM将在行运期也留保注释,因此可以通过反射机制取读注解的信息。
/ L1 h" G6 R! D; W/ i
& s: U6 X& F) e/ m9 F/ Z
3、@Documented 将此注解含包在 javadoc 中
H& h3 g# |8 R U/ b x
4、@Inherited 许允类子承继父类中的注解
' {5 |# f. y* ~" _0 M* L# L9 D
5、@Deprecated 表现前当元素是不赞同应用的。
a3 y, A+ `! n% M" U* g
6、@Override 表现前当方法是盖覆父类的方法。
; X `- A2 x# Q/ [+ @; }
7、@SuppressWarnings 表现闭关一些不当的编译器告警信息。
ava注解是附加在代码中的一些元信息,用于一些具工在编译、行运时行进剖析和应用,起到说明、配置的能功。
注解不会也不能影响代码的现实逻辑,仅仅起到辅助性的作用。含包在 java.lang.annotation 包中。
1、元注解
元注解是指注解的注解。含包 @Retention @Target @Document @Inherited四种。
1.1、@Retention: 定义注解的留保策略
@Retention(RetentionPolicy.SOURCE) //注解仅存在于码源中,在class字节码文件中不含包
@Retention(RetentionPolicy.CLASS) // 默许的留保策略,注解会在class字节码文件中存在,但行运时法无取得,
@Retention(RetentionPolicy.RUNTIME) // 注解会在class字节码文件中存在,在行运时可以通过反射获失掉
1.2、@Target:定义注解的作用目标
其定义的码源为:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
ElementType[] value();
}
@Target(ElementType.TYPE) //接口、类、枚举、注解
@Target(ElementType.FIELD) // 字段、枚举的量常
@Target(ElementType.METHOD) // 方法
@Target(ElementType.PARAMETER) // 方法参数
@Target(ElementType.CONSTRUCTOR) // 构造函数
@Target(ElementType.LOCAL_VARIABLE) // 局部量变
@Target(ElementType.ANNOTATION_TYPE) // 注解
@Target(ElementType.PACKAGE) / // 包
由以上的码源可以道知,他的elementType 可以有多个,一个注解可以为类的,方法的,字段的等等
1.3、@Document:说明该注解将被含包在javadoc中
1.4、@Inherited:说明类子可以承继父类中的该注解
2、java 注解的自定义
面下是自定义注解的一个例子
@Documented
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Yts {
public enum YtsType{util,entity,service,model};
public YtsType classType() default YtsType.util;
}
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Inherited
public @interface HelloWorld {
public String name()default "";
}
@Retention(RetentionPolicy.RUNTIME)
定义的这个注解是注解会在class字节码文件中存在,在行运时可以通过反射获失掉。
@Target({ElementType.TYPE,ElementType.METHOD})
因此这个注解可是以类注解,也可是以方法的注解
这样一个注解就自定义好了,当然注解面里的成员可以为基本的数据型类,也可以为数据,Object等等
3 注解是定义好了,那么怎么来失掉,剖析注解呢?
java的反射机制可以帮助,失掉注解,代码如下:
public class ParseAnnotation {
public void parseMethod(Class clazz) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, SecurityException, NoSuchMethodException, InstantiationException{
Object obj = clazz.getConstructor(new Class[]{}).newInstance(new Object[]{});
for(Method method : clazz.getDeclaredMethods()){
HelloWorld say = method.getAnnotation(HelloWorld.class);
String name = "";
if(say != null){
name = say.name();
method.invoke(obj, name);
}
Yts yts = (Yts)method.getAnnotation(Yts.class);
if(yts != null){
if(YtsType.util.equals(yts.classType())){
System.out.println("this is a util method");
}else{
System.out.println("this is a other method");
}
}
}
}
@SuppressWarnings("unchecked")
public void parseType(Class clazz) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException{
Yts yts = (Yts) clazz.getAnnotation(Yts.class);
if(yts != null){
if(YtsType.util.equals(yts.classType())){
System.out.println("this is a util class");
}else{
System.out.println("this is a other class");
}
}
}
}
前一个方法是剖析失掉方法注解的,后一个方法是失掉类注解的
以下是测试方法类
@Yts(classType =YtsType.util)
public class SayHell {
@HelloWorld(name = " 小明 ")
@Yts
public void sayHello(String name){
if(name == null || name.equals("")){
System.out.println("hello world!");
}else{
System.out.println(name + "say hello world!");
}
}
}
public static void main(String[] args) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, SecurityException, NoSuchMethodException, InstantiationException {
ParseAnnotation parse = new ParseAnnotation();
parse.parseMethod(SayHell.class);
parse.parseType(SayHell.class);
}
1、Annotation的任务道理:
JDK5.0中供提了注解的能功,许允开发者定义和应用自己的注解型类。该能功由一个定义注解型类的语法和描述一个注解声明的语法,取读注解的API,一个应用注解修饰的class文件和一个注解处置具工成组。
Annotation不并直接影响代码的语义,但是他可以被做看是序程的具工或者库类。它会反过来对正在行运的序程语义有所影响。
Annotation可以冲源文件、class文件或者在行运时通过反射机制多种式方被取读。
2、@Override注解:
java.lang
注释型类 Override
@Target(value=METHOD)
@Retention(value=SOURCE)
public @interface Override
表现一个方法声明盘算重写类超中的另一个方法声明。如果方法利用此注释型类行进注解但没有重写类超方法,则编译器会成生一条错误消息。
@Override注解表现类子要重写父类的对应方法。
Override是一个Marker annotation,用于标识的Annotation,Annotation名称本身表现了要给具工序程的信息。
面下是一个应用@Override注解的例子:
class A {
private String id;
A(String id){
this.id = id;
}
@Override
public String toString() {
return id;
}
}
3、@Deprecated注解:
java.lang
注释型类 Deprecated
@Documented
@Retention(value=RUNTIME)
public @interface Deprecated
用 @Deprecated 注释的序程元素,不励鼓序程员应用这样的元素,常通是因为它很危险或存在更好的择选。在应用不被赞同的序程元素或在不被赞同的代码中行执重写时,编译器会发出告警。
@Deprecated注解表现方法是不被提议应用的。
Deprecated是一个Marker annotation。
面下是一个应用@Deprecated注解的例子:
class A {
private String id;
A(String id){
this.id = id;
}
@Deprecated
public void execute(){
System.out.println(id);
}
public static void main(String[] args) {
A a = new A("a123");
a.execute();
}
}
4、@SuppressWarnings注解:
java.lang
注释型类 SuppressWarnings
@Target(value={TYPE,FIELD,METHOD,PARAMETER,CONSTRUCTOR,LOCAL_VARIABLE})
@Retention(value=SOURCE)
public @interface SuppressWarnings
示指应当在注释元素(以及含包在该注释元素中的全部序程元素)中取消示显指定的编译器告警。注意,在给定元素中取消示显的告警集是全部含包元素中取消示显的告警的超集。例如,如果注释一个类来取消示显某个告警,同时注释一个方法来取消示显另一个告警,那么将在此方法中同时取消示显这两个告警。
根据格风不同,序程员应当一直在最里层的嵌套元素上应用此注释,在那里应用才有效。如果要在特定的方法中取消示显某个告警,则应当注释该方法而不是注释它的类。
@SuppressWarnings注解表现制抑告警。
面下是一个应用@SuppressWarnings注解的例子:
@SuppressWarnings("unchecked")
public static void main(String[] args) {
List list = new ArrayList();
list.add("abc");
}
5、自定义注解:
应用@interface自定义注解时,动自承继了java.lang.annotation.Annotation接口,由编译序程动自实现其他细节。在定义注解时,不能承继其他的注解或接口。
自定义最简略的注解:
public @interface MyAnnotation {
}
应用自定义注解:
public class AnnotationTest2 {
@MyAnnotation
public void execute(){
System.out.println("method");
}
}
5.1、添加量变:
public @interface MyAnnotation {
String value1();
}
应用自定义注解:
public class AnnotationTest2 {
@MyAnnotation(value1="abc")
public void execute(){
System.out.println("method");
}
}
当注解中应用的属性名为value时,对其赋值时可以不指定属性的名称而直接写上属性值接口;除了value外意的量变名都要需应用name=value的式方赋值。
5.2、添加默许值:
public @interface MyAnnotation {
String value1() default "abc";
}
5.3、多量变应用枚举:
public @interface MyAnnotation {
String value1() default "abc";
MyEnum value2() default MyEnum.Sunny;
}
enum MyEnum{
Sunny,Rainy
}
应用自定义注解:
每日一道理
翻开早已发黄的页张,试着寻找过去所留下的点点滴滴的足迹。多年前的好友似乎现在看来已变得陌生,匆忙之间,让这维持了多年的友谊变淡,找不出什么亲切感,只是偶尔遇上,淡淡地微笑,如今也只能在这发黄的页张中找寻过去的那些让人难忘的,至少我可以握住这仅剩下一段的“丝线头”……
public class AnnotationTest2 {
@MyAnnotation(value1="a", value2=MyEnum.Sunny)
public void execute(){
System.out.println("method");
}
}
5.4、数组量变:
public @interface MyAnnotation {
String[] value1() default "abc";
}
应用自定义注解:
public class AnnotationTest2 {
@MyAnnotation(value1={"a","b"})
public void execute(){
System.out.println("method");
}
}
6、置设注解的作用围范:
@Documented
@Retention(value=RUNTIME)
@Target(value=ANNOTATION_TYPE)
public @interface Retention
示指注释型类的注释要留保多久。如果注释型类声明中不存在 Retention 注释,则留保策略默许为 RetentionPolicy.CLASS。
只有元注释型类直接用于注释时,Target 元注释才有效。如果元注释型类用作另一种注释型类的成员,则无效。
public enum RetentionPolicy
extends Enum<RetentionPolicy>
注释留保策略。此枚举型类的量常描述留保注释的不同策略。它们与 Retention 元注释型类一同应用,以指定留保多长的注释。
CLASS
编译器将把注释记录在类文件中,但在行运时 VM 不要需留保注释。
RUNTIME
编译器将把注释记录在类文件中,在行运时 VM 将留保注释,因此可以反射性地取读。
SOURCE
编译器要抛弃的注释。
@Retention注解可以在定义注解时为编译序程供提注解的留保策略。
属于CLASS留保策略的注解有@SuppressWarnings,该注解信息不会存储于.class文件。
6.1、在自定义注解中的应用例子:
@Retention(RetentionPolicy.CLASS)
public @interface MyAnnotation {
String[] value1() default "abc";
}
7、应用反射取读RUNTIME留保策略的Annotation信息的例子:
java.lang.reflect
接口 AnnotatedElement
全部已知现实类:
AccessibleObject, Class, Constructor, Field, Method, Package
表现前目正在此 VM 中行运的序程的一个已注释元素。该接口许允反射性地取读注释。由此接口中的方法回返的全部注释都是可不变并且可序列化的。调用者可以修改已赋值数组枚举成员的问访器回返的数组;这不会对其他调用者回返的数组发生任何影响。
如果此接口中的方法回返的注释(直接或间接地)含包一个已赋值的 Class 成员,该成员引用了一个在此 VM 中可不问访的类,则试图通过在回返的注释上调用关相的类回返的方法来取读该类,将致使一个 TypeNotPresentException。
isAnnotationPresent
boolean isAnnotationPresent(Class<? extends Annotation> annotationClass)
如果指定型类的注释存在于此元素上,则回返 true,否则回返 false。此方法要主是为了便于问访记标注释而计设的。
参数:
annotationClass - 对应于注释型类的 Class 象对
回返:
如果指定注释型类的注释存在于此象对上,则回返 true,否则回返 false
抛出:
NullPointerException - 如果给定的注释类为 null
从以下版本开始:
1.5
getAnnotation
<T extends Annotation> T getAnnotation(Class<T> annotationClass)
如果存在该元素的指定型类的注释,则回返这些注释,否则回返 null。
参数:
annotationClass - 对应于注释型类的 Class 象对
回返:
如果该元素的指定注释型类的注释存在于此象对上,则回返这些注释,否则回返 null
抛出:
NullPointerException - 如果给定的注释类为 null
从以下版本开始:
1.5
getAnnotations
Annotation[] getAnnotations()
回返此元素上存在的全部注释。(如果此元素没有注释,则回返度长为零的数组。)该方法的调用者可以意随修改回返的数组;这不会对其他调用者回返的数组发生任何影响。
回返:
此元素上存在的全部注释
从以下版本开始:
1.5
getDeclaredAnnotations
Annotation[] getDeclaredAnnotations()
回返直接存在于此元素上的全部注释。与此接口中的其他方法不同,该方法将疏忽承继的注释。(如果没有注释直接存在于此元素上,则回返度长为零的一个数组。)该方法的调用者可以意随修改回返的数组;这不会对其他调用者回返的数组发生任何影响。
回返:
直接存在于此元素上的全部注释
从以下版本开始:
1.5
面下是应用反射取读RUNTIME留保策略的Annotation信息的例子:
自定义注解:
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
String[] value1() default "abc";
}
应用自定义注解:
public class AnnotationTest2 {
@MyAnnotation(value1={"a","b"})
@Deprecated
public void execute(){
System.out.println("method");
}
}
取读注解中的信息:
public static void main(String[] args) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
AnnotationTest2 annotationTest2 = new AnnotationTest2();
//取得AnnotationTest2的Class实例
Class<AnnotationTest2> c = AnnotationTest2.class;
//取得要需处置的方法Method实例
Method method = c.getMethod("execute", new Class[]{});
//判断该方法是不是含包MyAnnotation注解
if(method.isAnnotationPresent(MyAnnotation.class)){
//取得该方法的MyAnnotation注解实例
MyAnnotation myAnnotation = method.getAnnotation(MyAnnotation.class);
//行执该方法
method.invoke(annotationTest2, new Object[]{});
//取得myAnnotation
String[] value1 = myAnnotation.value1();
System.out.println(value1[0]);
}
//取得方法上的全部注解
Annotation[] annotations = method.getAnnotations();
for(Annotation annotation : annotations){
System.out.println(annotation);
}
}
8、制限注解的应用:
制限注解应用@Target。
@Documented
@Retention(value=RUNTIME)
@Target(value=ANNOTATION_TYPE)
public @interface Target
示指注释型类所用适的序程元素的种类。如果注释型类声明中不存在 Target 元注释,则声明的型类可以用在任一序程元素上。如果存在这样的元注释,则编译器强制实行指定的应用制限。 例如,此元注释示指该声明型类是其自身,即元注释型类。它只能用在注释型类声明上:
@Target(ElementType.ANNOTATION_TYPE)
public @interface MetaAnnotationType {
...
}
此元注释示指该声明型类只可作为庞杂注释型类声明中的成员型类应用。它不能直接用于注释:
@Target({})
public @interface MemberType {
...
}
这是一个编译时错误,它明表一个 ElementType 量常在 Target 注释中涌现了不只一次。例如,以下元注释是法合的:
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.FIELD})
public @interface Bogus {
...
}
public enum ElementType
extends Enum<ElementType>
序程元素型类。此枚举型类的量常供提了 Java 序程中声明的元素的简略分类。
这些量常与 Target 元注释型类一同应用,以指定在什么情况下应用注释型类是法合的。
ANNOTATION_TYPE
注释型类声明
CONSTRUCTOR
构造方法声明
FIELD
字段声明(含包枚举量常)
LOCAL_VARIABLE
局部量变声明
METHOD
方法声明
PACKAGE
包声明
PARAMETER
参数声明
TYPE
类、接口(含包注释型类)或枚举声明
注解的应用制限的例子:
@Target(ElementType.METHOD)
public @interface MyAnnotation {
String[] value1() default "abc";
}
9、在帮助档文中参加注解:
要想在制造JavaDoc文件的同时将注解信息参加到API文件中,可以应用java.lang.annotation.Documented。
在自定义注解中声明构建注解档文:
@Documented
public @interface MyAnnotation {
String[] value1() default "abc";
}
应用自定义注解:
public class AnnotationTest2 {
@MyAnnotation(value1={"a","b"})
public void execute(){
System.out.println("method");
}
}
10、在注解中应用承继:
默许情况下注解不并会被承继到类子中,可以在自定义注解时加上java.lang.annotation.Inherited注解声明应用承继。
@Documented
@Retention(value=RUNTIME)
@Target(value=ANNOTATION_TYPE)
public @interface Inherited
示指注释型类被动自承继。如果在注释型类声明中存在 Inherited 元注释,并且户用在某一类声明中询查该注释型类,同时该类声明中没有此型类的注释,则将在该类的类超中动自询查该注释型类。此程过会重复行进,直到找到此型类的注释或达到了该类层次结构的顶层 (Object) 为止。如果没有类超有具该型类的注释,则询查将示指前当类没有这样的注释。
注意,如果应用注释型类注释类外以的任何事物,此元注释型类都是无效的。还要注意,此元注释仅促进从类超承继注释;对已现实接口的注释无效。
文章结束给大家分享下程序员的一些笑话语录: 现在社会太数字化了,所以最好是有一个集很多功能于一身的设备!