反射
概述
通过一个对象,表示一个类
能表示类的名字、构造器、方法、成员变量(field,字段)
快速入门
获取类对象的三种方式
-
对象.getClass()
-
类型.class
-
Class.forName("包名.类名")
类对象的方法
-
构造器
Constructor
-
成员变量
Field
-
方法
Method
-
名字
Name
public class ReflectPractice {
public static void main(String[] args) throws ClassNotFoundException {
// 1. 对象.getClass()
// Student student = new Student(null, null, null, null, null);
// Class<? extends Student> clz = student.getClass();
// 2. Class.forName("包名.类名")
// Class<?> clz = Class.forName("com.mobiletrain.domain.Student");
// 3. 类名.class
Class<Student> clz = Student.class;
// 能够访问的构造器
Constructor<?>[] constructors = clz.getConstructors();
// 所有的构造器
Constructor<?>[] declaredConstructors = clz.getDeclaredConstructors();
// 所有能够访问的成员变量
Field[] fields = clz.getFields();
// 所有成员变量
Field[] declaredFields = clz.getDeclaredFields();
// 获取所有能够访问的方法
Method[] methods = clz.getMethods();
// 所有在本类中编写的方法
Method[] declaredMethods = clz.getDeclaredMethods();
// 全限定类名(包名.类名)
String name = clz.getName();
// 类名
String simpleName = clz.getSimpleName();
System.out.println();
}
}
jar
java archive
在项目中导jar
- 创建jar包目录
点击屏幕左侧的项目导航
选择项目名,右键
New -> Directory(创建一个新目录)
在弹出的窗口中,为这个新目录起一个名字(libs)
- 把jar粘贴至此目录
在文件夹中,选择
javassist-3.26.0-GA.jar
、reflections-0.9.12.jar
选择libs目录,复制jar包,粘贴至此目录
- 告诉idea,此两个文件为库
选中此两个文件,右键
选择Add As Library
反射-包扫描
public class PackageScan {
public static void main(String[] args) {
// 2. 为 Reflections对象准备好扫描器
SubTypesScanner subTypesScanner = new SubTypesScanner(false);
// 1. 使用reflections进行扫描
Reflections reflections = new Reflections("com.mobiletrain", subTypesScanner);
Set<String> allTypes = reflections.getAllTypes();
System.out.println();
}
}
反射-方法调用
public static void main(String[] args) throws InvocationTargetException, NoSuchMethodException, IllegalAccessException {
// 获取一个方法对象
// 方法对象,能够表示一个方法
// Class<Student> studentClass = Student.class;
// Method setScore = studentClass.getMethod("setScore", String.class, Integer.class);
Student stu = new Student(null, null, null, null, null);
invoke(stu, "setUsername", "张三");
invoke(stu, "setScore", "数学", 19);
invoke(stu, "setPassword", "123456");
invoke(stu, "setGender", "m");
System.out.println();
}
// 写一个方法,此方法接收3个参数
// 第1个参数: 对象
// 第2个参数: 调用的方法
// 第3个参数: 方法的实参
// 返回值: 调用函数之后的函数值
public static Object invoke(Object obj,
String methodName,
Object ... args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
// 第一次调用
// invoke(stu, "setUsername", "张三")
// 要依据以上内容,找到
// setName(String)
// 第二次调用
// invoke(stu, "setScore", "数学", 20)
// 要依据以上内容,找到
// setScore(String, Integer)
// 第一个要解决的课题:
// 将 ["张三"] -> [String]
// 将 ["数学", 20] -> [String, Integer]
Class[] argClasses = new Class[args.length];
for (int i = 0; i < args.length; i++) {
// "数学" -> String
// "张三" -> String
// 20 -> Integer
Class<?> argClass = args[i].getClass();
argClasses[i] = argClass;
}
// 根据方法名,以及制作好的argClasses数组
// 找到方法
Method method = obj.getClass().getDeclaredMethod(methodName, argClasses);
// stu.setUsername("张三")
// method.invoke(stu, "张三")
// stu.setScore("数学", 20)
// method.invoke(stu, "数学", 20)
Object result = method.invoke(obj, args);
return result;
}