Annotation的使用
@Target表示的是这个Annotation可以应用在哪里,是对Annotation应用的限制,如果没有这个标识的话,Annotation可以用在任何地方,比如类上,方法上,变量,属性上等,可以从java.lang.Enum.ElementType这个枚举里选择.
1.只能用在方法上的限制的应用
package com.test;
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
public @interface TargetTest {
String hello();
}
package com.test;
public class TargetClass {
@TargetTest(hello = "abc")
public void doSomething()
{
System.out.println("do something");
}
}
2.只能用于类上限制的应用
package com.test;
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
public @interface TargetTest {
String hello();
}
package com.test;
@TargetTest(hello = "abc")
public class TargetClass {
public void doSomething()
{
System.out.println("do something");
}
}
- 注解@Retention可以用来修饰注解,是注解的注解,称为元注解.
- Retention注解有一个属性value,是Retentionpolicy类型的,Enum RetentionPolicy是一个枚举值.
- 这个枚举值决定了Retention注解应该如何去保持,也可理解Rentention搭配RententionPolicy使用.RetentionPolicy有三个值:CLASS RUNTIME SOURCE
- 用@Retention(RetentionPolicy.CLASS)修饰的注解,表示注解的信息被保留在class文件(字节码文件)中,当程序编译时,但不会被虚拟机读取在运行的时候.
- 用@Retention(RetentionPolicy.RUNTIME)修饰的注解,表示注解的信息被保留在class文件(字节码文件)中,当程序编译时,会被虚拟机保留在运行时.
- 用@Retention(RetentionPolicy.SOURCE)修饰的注解,表示注解的信息会被编译器抛弃,不会留在class文件中,注解只会留在源文件中
- RetentionPolicy.RUNTIME可以让你从JVM中读取Annotation注解的信息,以便在分析程序的时候使用.
下面实际操作一下:自己创建一个注解,用源注解为其注解.
@Retention(RetentionPolicy.RUNTIME)//用源注解修饰自定义的注解,可以从JVM读取该annotation.
public @interface MyAnnotation {
String value() default "robin";//使用抽象方法,和普通接口一样,还可以定义默认值.
String world();
int[] array() default {2,4,5,6};
Class style() default String.class;
TargetTest hello() default @TargetTest(hello = "hahaha");//annotation也可以作为返回值返回.
}
下面就是正式使用自定义注解了
@MyAnnotation(value="robin",world="China",array={},style=int.class) //自定义annotation中的方法,可以为其赋上参数, 没有赋值就会使用默认的值
public class MyTest {
@MyAnnotation(hello=@TargetTest(hello="nihao"),world="America",array={1,2,3})
@Deprecated //被这个标签修饰的方法会出现过期的标记
public void output(){
System.out.println("output something!");
}
}
下面就用到反射了,通过反射得到我们想要的东西
public class MyReflection {
public static void main(String[] args) throws NoSuchMethodException, SecurityException, IllegalAccessException,IllegalArgumentException, InvocationTargetException{
MyTest myTest = new MyTest();
Class<MyTest> c = MyTest.class; //得到Mytest类的信息
Method method = c.getMethod("output", new Class[] {}); //指定方法的名称,new Class[]{里面指定参数的类型}如果是output(String,name,int num),那么就是这样("output",new Class[]{String.class,int.class})
if(MyTest.class.isAnnotationPresent(MyAnnotation.class)){ //判断该类有没有使用MyAnnotattion的注解
System.out.println("have annotation");
}
if(method.isAnnotationPresent(MyAnnotation.class)){ //判断该方法有没有使用MyAnnotattion的注解
method.invoke(myTest, null); //调用方法的类,要传入的参数
MyAnnotation myAnnotation=method.getAnnotation(MyAnnotation.class); //获取annotattion的实例
String value=myAnnotation.value();
String world=myAnnotation.world();
System.out.println(value+","+world);
System.out.println(myAnnotation.array().length);
System.out.println(myAnnotation.hello().hello());
System.out.println(myAnnotation.style());
}
Annotation[] annotations=method.getAnnotations();
for(Annotation annotation:annotations){
System.out.println(annotation.annotationType().getName());
}
}
}