注解的意义:
注解在反射机制中被大量调用,可以便于我们更准确的使用反射机制操作一个类。 注解在框架中被大量的应用。
注解可以通过java内置的注解:@Target标注,用于指定当前注解可以在什么地方被使用。 * @Target的选项都被定义在ElementType中。
常用的值: ElementType.TYPE:在类上可以使用当前注解 ElementType.FIELD:在属性上可以使用当前注解 ElementType.CONSTRUCTOR:在构造方法上可以使用当前注解 ElementType.METHOD:在方法上可以使用当前注解 ElementType.PACKAGE:在包上可以使用当前注解
如果当前注解没有使用@Target注解标注,那么当前注解可以在任何注解可以使用的地方被应用。 如果希望同时在几个可选地方使用时,应当如下指定: @Target({ElementType.TYPE,ElementType.METHOD,...}) 以数组形式包含可以指定位置的选项并传入@Target
@Retention注解,该注解用于标注当前注解的保留级别,有三个可选值 RetentionPolicy.CLASS : 当前注解保留在编译后的字节码文件中,但是不可被反射机制操作 RetentionPolicy.SOURCE : 当前注解仅保留在源代码中。 RetentionPolicy.RUNTIME : 当前注解保留在编译后的字节码文件中,可被反射机制操作。 注意:如果@Retention不指定,默认级别为CLASS
package reflect;
@Target(ElementType.TYPE)//类
//@Target({ElementType.TYPE,ElementType.Fild})//以数组形式包含可以指定位置的选项并传入
@Retention(RetentionPolicy.RUNTIME)//由于我们都是在反射机制中大量使用注解,因此我们通常要显示的
//标注注解的保留级别为RUNTIME!!!
public @interface AutoRunClass {
}
注解可以定义参数。格式:类型 参数名() [default 默认值] 如下: int value() 当定义了该参数后,那么使用注解时可以为其传递参数值,如: @AutoRunMethod(8) 此时value参数值为:8
package reflect;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoRunMethod {
String value() defalt "good";
被标记注解的类中则为
@AutoRunMethod(“verygood”) 此时value参数值为:"verygood"
@AutoRunMethod() 若不传参此时value参数值为:m默认值"good"
注意:如果当前注解仅指定了一个参数,那么参数名尽量使用value。这样外面给该参数传值时可省去参数名。 如: @AutoRunMethod(8) 此时value参数的值为8 否则,正常使用注解传参的语法格式为:@注解名(参数名=参数值) 例如: 当前注解中指定的参数为: int count; 此时使用当前注解并传参时应当写为: @AutoRunMethod(count=2)
两个以上参数时,无论哪个参数的名字叫value都要用name=value的格式传递参数。 int count(); String name();
那么使用当前注解传参时的格式: @AutoRunMethod(count=6,name="罗") 注意:这里传参的顺序可以和参数定义的顺序不一致。即: @AutoRunMethod(name="罗",count=6)也是允许的。
Method,Constructor,Field等都有这个方法: boolean isAnnotationPresent(Class cls) 用于判断:方法,构造器,属性等是否又被某个特定的注解标注
package reflect;
import java.io.File;
import java.lang.reflect.Method;
import java.net.URISyntaxException;
/**
* 自动调用那些与当前类Test4在同一个包中被@AutoRunClass标注的类中那些被@AutoRunMethod标注的方法
*/
public class Test4 {
public static void main(String[] args) throws Exception {
File dir = new File(
Test4.class.getResource(".").toURI()//或取同级的
);
File[] files = dir.listFiles(f->f.getName().endsWith(".class"));//获取同级的方法
for(File file : files){
String fileName = file.getName();
String className = fileName.substring(0,fileName.indexOf("."));
//拆分按照0到点的位置 xxxx.java 获取xxxx 方法名
Class cls = Class.forName(Test4.class.getPackage().getName()+"."+className);
//获取类对象
if(cls.isAnnotationPresent(AutoRunClass.class)) {//判断该方法师傅被注解标注
Object o = cls.newInstance();
Method[] methods = cls.getDeclaredMethods();
//获取被注解标注的所有方法的所有方法
for (Method method : methods) {
if (method.isAnnotationPresent(AutoRunMethod.class)) {
//判断是否被注解若是就调用方法
method.invoke(o);
}
}
}
}
}
}
method.getAnnotation(AutoRunMethod.class);
package reflect;
import java.lang.reflect.Method;
public class ReflectDmeo10 {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
Class cls=Class.forName("reflect.Person");
Object obj=cls.newInstance();
Method[] methods=cls.getDeclaredMethods();
for (Method method : methods) {
if(method.isAnnotationPresent(AutoRunMehod.class)){
//当我们确定一个方法被特定的注解标注后,
//就可以获取该注解从而的得到注解中传递的参数
AutoRunMehod arm=method.getAnnotation(AutoRunMehod.class);
int value=arm.value();
//获取该方法上的@AutoRunMethod注解上传递的参数值
int e=arm.asd();
System.out.println(method.getName()+"注解AutoMethod中指定的参数value为"+arm);
}
}
}
}
当我们确定一个方法被特定的注解标注后,就可以获取该注解从而得到注解中传递的参数