首先我们在学习原理前,需要先了解下反射
Reflection(反射)
在有些场景中,需要在运行时动态的操作类的成员,比如在运行时根据数据库中提供具体的类名或方法名,或者根据字符串来动态实例化对象或者调用方法时,就不能通过new()对象,的方式 创建类或者 是使用类中的方法了
关键思路在于创建 class对象
我们写的每一个类如下被虚拟机解析
JVM是如何创建 Class 对象的
首先通过.java 编译成 .class 文件,然后通过 Class Loader 加载到内存, 随后JVM根据内存中的信息创建响应的Class 对象。
如何获取某个类的Class 对象
-
直接用类名.class, 就是某个类的class对象
Class<User> userClass = User.class;
-
通过对象的.getClass() 方法,我们在编译阶段无法准确地判断Class对象的确切类型
Class<?> clazz = user.getClass(); //使用通配符
-
通过Class.forName() 方法获取 类型
Class<?> class = Class.forName("org.blcu.taco.User")
- 参数为完全类的限定名
- 通过这种方法获取类的对象时,类的静态代码块会立即执行。
某个类的Class对象的常用操作
假设我们有一个类为:
public class Son {
private final String idNum;
public String school;
public String name;
private static final String staticField = "Son static field"
public Son (String idNum,String name) {
this.idNum = idNum;
this.name = name;
}
static {
System.out.println("Son static block");
}
public static void sayHello() {
System.out.println("Son say hello");
}
public void sayHi(String name) {
System.out.println("Son say hi to " + name);
}
private static void sayBye() {
System.out.println("Son sayBye");
}
private static void sayBye(String what) {
System.out.println("Son".concat(what));
}
private void sayBye1() {
System.out.println(this.name+"Son sayBye1");
}
}
那当我们获取了Son 的 Class 对象后,我们能做什么操作呢?
-
获取所有字段名
// 获取Son类的Class对象 Class<?> aClass = Class.forName("studydemo.reflection.Son"); // 通过这种方法获取类的对象时,类的静态代码块会立即执行, 此时我们的静态代码块就会执行,输出:son static block // 获取反射类中所有的公有字段 Field[] fields = aClass.getFields(); for (Field field : fields) { System.out.println(field.getName()); } // 获取所有的字段名,包括共有和私有 Field[] declaredFields1 = aClass.getDeclaredFields(); for (Field field : declaredFields1) { System.out.println(field.getName()); }
-
获取本类中所有的方法名
// 获取Son类的Class对象 Class<?> aClass = Class.forName("studydemo.reflection.Son"); // 获取所有的方法名 Method[] declaredMethods = aClass.getDeclaredMethods(); for (Method declaredMethod : declaredMethods) { System.out.println(declaredMethod