将类的各个组成部分封装为其他对象,这就是反射的机制。
反射的好处:
- 可以在程序运行过程中,操作这些对象
- 可以解耦,提高程序的可扩展性
方式一:Class.forName(“全类名”):将字节码文件加载进内存,返回 Class 对象
方式二:类名.class:通过类名的属性 class 获取
方式三:对象.getClass():getClass() 方法在 Object 类中定义着
注意:同一个字节码文件在一次程序的运行中,只会被加载一次,无论通过哪一种方式获取的 Class 对象都是同一个。
package com.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Person {
private String name;
private Integer age;
}
package com.basic;
import com.entity.Person;
public class Demo {
public static void main(String[] args) throws ClassNotFoundException {
// 此方式获取 Class 多用于配置文件中,将类名定义在配置文件中,读取文件,加载类
Class> personClass1 = Class.forName("com.entity.Person"); // 包名+类名:全类名
System.out.println(personClass1);
// 多用于参数的传递(我们经常用)
Class personClass2 = Person.class;
System.out.println(personClass2);
Person p = new Person();
Class extends Person> personClass3 = p.getClass();
System.out.println(personClass3);
// 比较3个 Class 实例是否相等
System.out.println(personClass1 == personClass2);
System.out.println(personClass2 == personClass3); // 结果都为 true,所以创建的都是同一个实例,只会加载一次,产生一个实例
}
}
2. 利用 Class 对象获取成员变量们
- Field[] getFields():获取所有 public 修饰的成员变量
- Field getField(String name):获取指定名称的 public 修饰的成员变量
- Field[] getDeclaredFields():获取所有的成员变量,不考虑修饰符
- Field getDeclaredField(String name):获取指定名称的成员变量,不考虑修饰符
- void set(Object obj, Object value):给成员变量设置值
- get(Object obj):获取成员变量的值
- setAccessible(true):暴力反射,使其能够访问 private 修饰的成员变量
package com.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Person {
private String name;
private Integer age;
public String a;
public String testA;
protected String b;
String c;
}
package com.basic;
import com.entity.Person;
import java.lang.reflect.Field;
import java.util.Arrays;
public class Demo {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
// 获取到 Class 实例
Class personClass = Person.class;
// 获取所有 public 修饰的成员变量
Field[] fields = personClass.getFields();
System.out.println(Arrays.toString(fields));
// 获取指定名称 public 修饰的成员变量
Field testA = personClass.getField("testA");
System.out.println(testA);
// 给字段设置值
Person p = new Person();
testA.set(p, "张三"); // 通过反射的方式设置值
// 取字段的值
System.out.println(testA.get(p)); // 通过反射的方式取值
// 获取所有的成员变量,不考虑修饰符
Field[] declaredFields = personClass.getDeclaredFields();
System.out.println(Arrays.toString(declaredFields));
// 获取指定名称的成员变量,不考虑修饰符
Field name = personClass.getDeclaredField("name");
System.out.println(name);
// 给 private 字段设置值
name.setAccessible(true); // 暴力反射,使其能够访问 private 的修饰符的变量
name.set(p, "李四");
System.out.println(name.get(p));
}
}
3. 利用 Class 对象获取构造方法
- Constructor>[] getConstructors():获取所有 public 修饰的构造方法
- Constructor getConstructor(类>…parameterfTypes):获取指定参数列表的 public 修饰的构造方法
- Constructor getDeclaredConstructor(类>…parameterfTypes):获取指定参数列表的构造方法,不考虑修饰符
- Constructor>[] getDeclaredConstructors():获取所有的构造方法,不考虑修饰符
- T newInstance(Object…initargs):用得到的构造方法创建对象
- 如果使用空参构造函数创建对象,操作可以简化:Class 对象的 newInstance 方法
package com.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Person {
private String name;
private Integer age;
}
package com.basic;
import com.entity.Person;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
public class Demo {
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
// 获取到 Class 实例
Class personClass = Person.class;
// 获取所有 public 修饰的构造方法
Constructor>[] constructors = personClass.getConstructors();
System.out.println(Arrays.toString(constructors));
// 获取指定名称的 public 修饰的构造方法
Constructor constructor = personClass.getConstructor(String.class, Integer.class);
System.out.println(constructor);
// 用反射的方式去创建对象
Person person = constructor.newInstance("张三", 18);
System.out.println(person);
// 获取空参的构造方法的简化模式
Person person1 = personClass.newInstance();
System.out.println(person1);
}
}
4. 利用 Class 对象获取成员方法们
- Method[] getMethods():获取类里面所有的 public 方法,包括父类里面的 pubic 方法
- Method getMethod(String name,类>…parameterTypes):获取指定的 public 修饰的方法
- Method[] getDeclaredMethods():获取类里面声明的所有方法,不包括父类的方法
- Method getDeclaredMethod(String name, 类>…parameterTypes)
- Object invoke(Object obj, Object…args):执行方法
- String getName:获取方法名称
package com.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Person {
private String name;
private Integer age;
private String lookMovie(String movieName, int age) {
System.out.println(movieName + "::" + age);
return movieName;
}
}
package com.basic;
import com.entity.Person;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
public class Demo {
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
// 获取到 Class 实例
Class personClass = Person.class;
// 获取所有 public 修饰的方法(包括父类的方法)
Method[] methods = personClass.getMethods();
System.out.println(Arrays.toString(methods));
// 获取指定的 public 修饰的方法
Method setName = personClass.getMethod("setName", String.class);
System.out.println(setName);
// 执行这个方法
Person person = personClass.newInstance(); // 用反射的方式创建空参构造方法
setName.invoke(person, "张三"); // 执行方法
System.out.println(person);
// 获取所有的方法(不包含父类的方法)
Method[] declaredMethods = personClass.getDeclaredMethods();
System.out.println(Arrays.toString(declaredMethods));
// 获取指定的方法(private 和 public 修饰都可以)
Method lookMovie = personClass.getDeclaredMethod("lookMovie", String.class, int.class);
System.out.println(lookMovie);
// 执行私有方法
lookMovie.setAccessible(true); // 暴力反射,使执行 private 修饰的方法不报错
Object invoke = lookMovie.invoke(person, "李四", 28);
System.out.println(invoke);
}
}



