项目结构
src/com/zzn/reflect
/annctations
/AutoRunClass.java
/AutoRunMethod.java
/Person.java
/ReflectDemo
1、创建注解
创建AutoRunClass注解,该注解只用在类上。
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.TYPE,ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoRunClass {
}
创建AutoRunMethod注解,该注解只用在方法上,并且要设置传递的值。
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 {
//设置注解的默认值
int value() default 1;
}
2、创建类,并且添加注解
import com.zzn.reflect.annctations.AutoRunClass;
import com.zzn.reflect.annctations.AutoRunMethod;
@AutoRunClass
public class Person {
private String name;
private int age;
private String sex;
public Person(){}
public Person(String name, int age, String sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
@AutoRunMethod(value = 5)
public void sayHello(){
System.out.println(name+": hello");
}
}
3、实现:
- 输出当前 Student类 所属包下面的 被 @AutoRunClass 标注过的类名。
- 调用被 @AutoRunMethod 标注过的公开且无参的方法。
- 获取注解的值,根据值设置调用方法的次数
import com.zzn.reflect.annctations.AutoRunClass;
import com.zzn.reflect.annctations.AutoRunMethod;
import java.io.File;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class ReflectDemo {
public static void main(String[] args) throws Exception {
// 1.定位到 E:\code\JavaCode\JavaBigData\JavaBase\target\classes\com\zzn\reflect
File dir = new File(Person.class.getResource(".").toURI());
System.out.println(dir);
// 2.获取 dir目录下的全部的.class文件
File[] files = dir.listFiles(f -> f.getName().endsWith(".class"));
for (File file : files) {
// 3.获取全限定名
// 获取类名 Person
String namePath = file.getName().substring(0, file.getName().indexOf("."));
//根据 Person这个类的包名 + 类名 来拼接全限定名 com.zzn.reflect.Person
String className = Person.class.getPackage().getName() + "." + namePath;
// 4.根据全限定名加载类
Class cls = Class.forName(className);
// 5、判断该类是否被标注过,被标记过就进行输出
boolean annotationPresent = cls.isAnnotationPresent(AutoRunClass.class);
if (annotationPresent) {
System.out.println(className + "被标注过了"); //输出被@AutoRunClass 标注过的类名
Object obj = cls.newInstance();
// 6.获取类里面的全部的方法名
Method[] methods = cls.getDeclaredMethods();
for (Method method : methods) {
// 7.判断该方法是否被标注过,被标记过就进行输出
boolean annotationPresent1 = method.isAnnotationPresent(AutoRunMethod.class);
// 调用被 @AutoRunMethod 标注过的公开且无参的方法
if (annotationPresent1 & method.getParameterCount() == 0 & method.getModifiers() == Modifier.PUBLIC) {
System.out.println(method.getName() + "被标注过了");
System.out.println("自动调用方法:" + method.getName() + "()");
// 8.获取注解的参数,并调用方法
AutoRunMethod annotation = method.getAnnotation(AutoRunMethod.class);
int value = annotation.value();
for (int i = 0; i < value; i++) {
method.invoke(obj);
}
}
}
}
}
}
}
扩展:
1、元注解:
@Target() 用于描述注解的使用范围
ElementType.TYPE 表示只能在类或接口上用 ElementType.FIELD 表示只能在属性上用 ElementType.LOCAL_VARIABLE 表示只能在局部变量上用 ElementType.METHOD 表示只能在方法上用 ElementType.PARAMETER 表示只能在参数上用 ElementType.CONSTRUCTOR 表示只能在构造器上用 ElementType.ANNOTATION_TYPE 表示只能在注解上用 ElementType.PACKAGE 表示只能在包上用
@Retention() 用于描述当前注解保留的时间长短
RetentionPolicy.SOURCE 在源文件中有效(即源文件保留)
RetentionPolicy.CLASS 在class文件中有效(即class保留)
RetentionPolicy.RUNTIME 在运行时有效(即运行时保留)
2、Class类/Method类/AutoRunMethod类的方法
getParameterCount() 获取方法参数的个数
getModifiers() 获取方法的访问修饰符
isAnnotationPresent() 判断某个类/方法/属性/构造器有没有被某个注解标注过
getAnnotation(AutoRunMethod.class); 获取方法的注解