使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口,由编译程序自动完成其他细节。在定义注解时,不能继承其他的注解或接口。@interface用来声明一个注解,其中的每一个方法实际上是声明了一个配置参数。 方法的名称就是参数的名称,返回值类型就是参数的类型 (返回值类型只能是基本类型、Class、String、enum)。可以通过default来声明参数的默认值。
定义注解格式: public @interface 注解名 {定义体}
1.所有基本数据类型(int,float,boolean,byte,double,char,long,short) 2.String类型 3.Class类型 4.enum类型 5.Annotation类型 6.以上所有类型的数组
Annotation类型里面的参数该怎么设定: 第一,只能用public或默认(default)这两个访问权修饰.例如,String value();这里把方法设为defaul默认类型; 第二,参数成员只能用基本类型byte,short,char,int,long,float,double,boolean八种基本数据类型和 String,Enum,Class,annotations等数据类型,以及这一些类型的数组.例如,String value();这里的参数成员就为String; 第三,如果只有一个参数成员,最好把参数名称设为"value",后加小括号.例:下面的例子FruitName注解就只有一个参数成员。
简单的自定义注解和使用注解实例:
package 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; /** * 水果名称注解 * @author peida * */ @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface FruitName { String value() default ""; } 复制代码
package 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; /** * 水果颜色注解 * @author peida * */ @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface FruitColor { /** * 颜色枚举 * @author peida * */ public enum Color{ BULE,RED,GREEN}; /** * 颜色属性 * @return */ Color fruitColor() default Color.GREEN; } 复制代码
package annotation; import annotation.FruitColor.Color; public class Apple { @FruitName("Apple") private String appleName; @FruitColor(fruitColor=Color.RED) private String appleColor; public void setAppleColor(String appleColor) { this.appleColor = appleColor; } public String getAppleColor() { return appleColor; } public void setAppleName(String appleName) { this.appleName = appleName; } public String getAppleName() { return appleName; } public void displayName(){ System.out.println("水果的名字是:苹果"); } } 复制代码
元注解的作用就是负责注解其他注解。Java5.0定义了4个标准的meta-annotation类型,它们被用来提供对其它 annotation类型作说明。Java5.0定义的元注解: 1.@Target ,用于描述注解的使用范围(方法、构造方法、成员变量、枚举值)
取值(ElementType)有:
1.CONSTRUCTOR:用于描述构造器 2.FIELD:用于描述域 3.LOCAL_VARIABLE:用于描述局部变量 4.METHOD:用于描述方法 5.PACKAGE:用于描述包 6.PARAMETER:用于描述参数 7.TYPE:用于描述类、接口(包括注解类型) 或enum声明
2.@Retention,表示需要在什么级别保存该注释信息,用于描述注解的生命周期
取值(RetentionPoicy)有:
1.SOURCE:在源文件中有效(即源文件保留) 2.CLASS:在class文件中有效(即class保留) 3.RUNTIME:在运行时有效(即运行时保留)(属性值是RUTIME,这样注解处理器可以通过反射,获取到该注解的属性值)
3.@Documented用于描述其它类型的annotation应该被作为被标注的程序成员的公共API,因此可以被例如javadoc此类的工具文档化 4.@Inherited @Inherited 元注解是一个标记注解,@Inherited阐述了某个被标注的类型是被继承的。如果一个使用了@Inherited修饰的annotation类型被用于一个class,则这个annotation将被用于该class的子类。
第一步:新建一个annotation,名字为:MyAnnotation.java。
package com.dragon.test.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Created by gmq on 2015/9/10. */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface MyAnnotation { String hello () default "hello"; String world(); } 复制代码
第二步:建立一个MyTest.java 来使用上面的annotation。
package com.dragon.test.annotation; /** * Created by gmq on 2015/9/10. */ public class MyTest { @MyAnnotation(hello = "Hello,Beijing",world = "Hello,world") public void output() { System.out.println("method output is running "); } } 复制代码
第三步:用反射机制来调用注解中的内容
package com.dragon.test.annotation; import java.lang.annotation.Annotation; import java.lang.reflect.Method; /** * 用反射机制来调用注解中的内容 * Created by gmq on 2015/9/10. */ public class MyReflection { public static void main(String[] args) throws Exception { // 获得要调用的类 Class<MyTest> myTestClass = MyTest.class; // 获得要调用的方法,output是要调用的方法名字,new Class[]{}为所需要的参数。空则不是这种 Method method = myTestClass.getMethod("output", new Class[]{}); // 是否有类型为MyAnnotation的注解 if (method.isAnnotationPresent(MyAnnotation.class)) { // 获得注解 MyAnnotation annotation = method.getAnnotation(MyAnnotation.class); // 调用注解的内容 System.out.println(annotation.hello()); System.out.println(annotation.world()); } System.out.println("----------------------------------"); // 获得所有注解。必须是runtime类型的 Annotation[] annotations = method.getAnnotations(); for (Annotation annotation : annotations) { // 遍历所有注解的名字 System.out.println(annotation.annotationType().getName()); } } } 复制代码
输出:
Hello,Beijing Hello,world
参考: www.cnblogs.com/gmq-sh/p/47…
注解(Annotation),也叫元数据(Metadata),是Java5的新特性,JDK5引入了Metadata很容易的就能够调用Annotations。注解与类、接口、枚举在同一个层次,并可以应用于包、类型、构造方法、方法、成员变量、参数、本地变量的声明中,用来对这些元素进行说明注释。
(1)以@interface关键字定义 (2)注解包含成员,成员以无参数的方法的形式被声明。其方法名和返回值定义了该成员的名字和类型。 (3)成员赋值是通过@Annotation(name=value)的形式。 (4)注解需要标明注解的生命周期,注解的修饰目标等信息,这些信息是通过元注解实现。
以 java.lang.annotation 中定义的 Target 注解来说明:
@Retention(value = RetentionPolicy.RUNTIME) @Target(value = { ElementType.ANNOTATION_TYPE } ) public @interface Target { ElementType[] value(); } 复制代码
源码分析如下: 第一:元注解@Retention,成员value的值为RetentionPolicy.RUNTIME。 第二:元注解@Target,成员value是个数组,用{}形式赋值,值为ElementType.ANNOTATION_TYPE 第三:成员名称为value,类型为ElementType[] 另外,需要注意一下,如果成员名称是value,在赋值过程中可以简写。如果成员类型为数组,但是只赋值一个元素,则也可以简写。如上面的简写形式为:
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.ANNOTATION_TYPE) public @interface Target { ElementType[] value(); } 复制代码
注解的分类有两种分法:
第一种分法
1、基本内置注解,是指Java自带的几个Annotation,如@Override、Deprecated、@SuppressWarnings等;
2、元注解(meta-annotation),是指负责注解其他注解的注解,JDK 1.5及以后版本定义了4个标准的元注解类型,如下:
@Target @Retention @Documented @Inherited 3、自定义注解,根据需要可以自定义注解,自定义注解需要用到上面的meta-annotation
参考: blog.csdn.net/github_3518…
@Retention是java当中的一个元注解,该元注解通常都是用于对软件的测试
@Retention(RetentionPolicy.RUNTIME) @interface Task{.......} 复制代码
参数RetentionPolicy.RUNTIME就说明了,@Task注解在程序运行时是可见的 RetentionPolicy的枚举类型还有SOURCE、CLASS分别指定注解对于那个级别是可见的,但是, 我们一般都是用RUNTIME ,因为这是在程序运行时可以对注解进行读取,从而易于软件的测试
在java虚拟机JVM在运行时,就会将类进行加载,这时,每个类都会生成一个Class数据类型的对象(Class类在java.lang.Class中),这个对象就是对应类的“运行时对象”,通过这个运行时对象,就能够获取对应类的许多信息,也就是说, 运行时对象实际就是对应类的一个映射 ,这就java的内省反射机制
① 获取对应类的Class数据类型的运行时对象的引用——getClass()
public class Point{.....} //声明一个类 Point pt = new Point(); //创建对应类的实例对象 Class cls = pt.getClass() ; //则cls 就指向了Point类的运行时对象 复制代码
②运行时对象cls的成员函数
<1>public String getName() 返回对应类的类名 <2>public boolean isAnnotationPresent(注解名.class) 判定指定的"注解"是否在运行时注解了 cls 的对应类 <3>public boolean isAnnotation(); 判定cls 是否在运行时被任何注解 注解过 <4>public A getAnnotation(注解名.class) A 指的是一个注解的类型,具体用法如下: @Retention(RetentionPolicy.RUNTIME) //指定@Task运行时可见 @interface Task{String descirption(); } @Task(descroption="NoFinished") //为computer作注 class Computer{.....} 则 Computer my = new Computer() ; Class cls = my.getClass() ; Task tk = (Task) cls.getAnnotation(Task.class); //这时 tk 就指向了标注Computer的注解@Task tk.description(); //调用@Task中的description(),输出"NoFinishing" <5> public Method[] getMethods() 返回由对应类中的所有的方法形成的Method数组,每个Method对象都唯一对应 一个对应类中的方法,通过Method[i]就可以获得对应方法的信息 (Method类在java.lang.reflect.Method中) 这个Method类也有很多成员方法,用来获取对应的方法的信息 如也有: public boolean isAnnotationPresent(注解名.class) 判定对应的方法是否被指定的注所注解 public A getAnnotation(注解名.class) 用法和上面的讲述的一样,之不过创建的注解型的引用变量指向的是 "标记对应方法的注解" 复制代码