一.什么是反射
Java 源码编译后生成 .class 字节码文件,类加载时会被 JVM 读取并加载到内存。在首次使用时,JVM 会为每个加载到内存的类生成唯一的 Class 对象,它是 .class 字节码在内存中的 "映射",包含了类的完整元数据(字段、方法、构造器、修饰符等)。结合Method/Field/Constructor 等反射工具类,在运行时动态获取类的元数据、调用类的成员,从而实现对类的间接操作。

二.反射解决的问题
反射机制是Java中用于解决在运行时获取类型(要求运行时这个类必须存在),然后用这个类型的Class对象来创建这个类对象,调用方法等操作。
Java 反射(Reflection)是 Java 语言的一个强大特性,它允许程序在运行时检查和操作类、接口、字段和方法的信息,而无需在编译时知道它们的名称。
三.Class对象有哪些

四.Class类
4.0 up自己做的图

4.1.怎么获取Class对象


4.2.coding
@Test
public void testStringClass()throws Exception{
//获取String类的Class对象
// (1)类名.class
Class c1 = String.class;
// (2)对象.getClass()
Class c2 = "hello".getClass();
// (3)Class.forName("类的全名称")
Class c3 = Class.forName("java.lang.String");
// - 类加载器.loadClass("类的全名称")
Class c4 = ClassLoader.getSystemClassLoader().loadClass("java.lang.String");
System.out.println(c1 == c2);
System.out.println(c1 == c3);
System.out.println(c1 == c4);
//上面是4种方式来获取同一种类型String的Class,在JVM中只有唯一的一个Class对象代表String类型。
}

4.3.Class类的方法
| 方法 | 作用 |
|---|---|
public boolean isArray() |
判断该 Class 对象是否代表一个数组类 |
public boolean isInterface() |
判断该 Class 对象是否代表一个接口 |
public boolean isPrimitive() |
判断该 Class 对象是否代表基本数据类型(如 int、boolean) |
public boolean isEnum() |
判断该 Class 对象是否代表一个枚举类 |
public boolean isAnnotation() |
判断该 Class 对象是否代表一个注解类型 |
public String getName() |
获取类的全限定名(如 java.lang.String) |
public String getSimpleName() |
获取类的简单名称(如 String) |
public Class<? super T> getSuperclass() |
获取该类的父类 Class 对象 |
public Class<?>[] getInterfaces() |
获取该类实现的所有接口 Class 对象数组 |
Class类的成员获取
| 方法 | 作用 |
|---|---|
public Field getField(String name) |
获取指定 public 字段 |
public Field[] getFields() |
获取所有 public 字段(含父类) |
public Field getDeclaredField(String name) |
获取当前类中任意权限的指定字段 |
public Field[] getDeclaredFields() |
获取当前类中所有字段(不含父类) |
public Method getMethod(String name, Class<?>... parameterTypes) |
获取指定 public 方法 |
public Method[] getMethods() |
获取所有 public 方法(含父类) |
public Method getDeclaredMethod(String name, Class<?>... parameterTypes) |
获取当前类中任意权限的指定方法 |
public Method[] getDeclaredMethods() |
获取当前类中所有方法(不含父类) |
public Constructor<T> getConstructor(Class<?>... parameterTypes) |
获取指定 public 构造器 |
public Constructor<?>[] getConstructors() |
获取所有 public 构造器 |
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) |
获取当前类中任意权限的指定构造器 |
public Constructor<?>[] getDeclaredConstructors() |
获取当前类中所有构造器 |
4.4利用Class类和Constuctor创建对象
4.4.1无参构造(用的多!推荐!)
@Test
public void testUseNoArgConstructorCreateObject() throws Exception{ //用的多,推荐!(建议每个类都保留无参构造)因为创建对象要简化,后面赋值成员有别的方法
Class<?> clazz = Class.forName("bean.Employee");
//获取无参构造
Constructor<?> noArgConstructor = clazz.getConstructor();
Object obj = noArgConstructor.newInstance();
/*//获取有参构造
Constructor<?> constructor = clazz.getConstructor(String.class,int.class,double.class);
//利用有参构造创建对象
Object obj = constructor.newInstance("Tom",18,5000);*/
System.out.println(obj);
}
4.4.2 有参构造
@Test
public void testUseArgsConstructorCreateObject() throws Exception{
Class<?> clazz = Class.forName("bean.Employee");
/*//获取无参构造
Constructor<?> noArgConstructor = clazz.getConstructor();
Object obj = noArgConstructor.newInstance();*/
//获取有参构造
Constructor<?> constructor = clazz.getConstructor(String.class,int.class,double.class);
//利用有参构造创建对象
Object obj = constructor.newInstance("Tom",18,5000);
System.out.println(obj);
}
4.5通过某个类的Class对象来操作属性
@Test
public void testAssignAttribute()throws Exception{
Class<?> clazz = Class.forName("bean.Employee");
//获取无参构造
Constructor<?> noArgConstructor = clazz.getConstructor();
Object obj = noArgConstructor.newInstance();
//System.out.println(obj);
/*//获取有参构造
Constructor<?> constructor = clazz.getConstructor(String.class,int.class,double.class);
//利用有参构造创建对象
Object obj = constructor.newInstance("Tom",18,5000);*/
/*//获取属性的类型和名称
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields){
System.out.println(field.getType() + " "+ field.getName());
}*/
Field nameField = clazz.getDeclaredField("name");
nameField.setAccessible(true);//因为姓名是私有属性,所以为了访问,先设置可访问性为true
nameField.set(obj,"Tom");
System.out.println(obj);
}

4.6通过Class和Method来操作方法
package reflect;
import org.junit.jupiter.api.Test;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class testOperateMethod {
@Test
public void testOperateMethod() throws Exception {
Class<?> rect = Class.forName("bean.Rectangle");
Constructor<?> constructor = rect.getConstructor();
Object obj = constructor.newInstance();
Field lengthField = rect.getDeclaredField("length");
Field widthField = rect.getDeclaredField("width");
lengthField.setAccessible(true);
widthField.setAccessible(true);
lengthField.set(obj, 10);
widthField.set(obj, 5);
System.out.println(obj);
Method getAreaMethod = rect.getMethod("area");
System.out.println(getAreaMethod.invoke(obj));
Method perimeterMethod = rect.getMethod("perimeter");
System.out.println(perimeterMethod.invoke(obj));
}
}
