系统:Win10
Java:1.8.0_333
IDEA:2020.3.4
Gitee:https://gitee.com/lijinjiang01/JavaWeb
反射:反射是指对于任何一个 Class 类,在“运行的时候”都可以直接得到这个类全部成分
在运行时,可以直接得到这个类的构造器对象:Constructor
在运行时,可以直接得到这个类的成员变量对象:Field
在运行时,可以直接得到这个类的成员方法对象:Method
这种运行时动态获取类信息以及动态调用类中成分的能力称为 Java 语言的反射机制
反射第一步都是先得到编译后的 Class 类对象,然后就可以得到 Class 的全部成分
反射的核心思想和关键就是:得到编译以后的 class 文件对象


获取 Class 类对象的三种方式:
Class 类中的一个静态方法:forName(String className)
Class c1 = Class.forName("com.lijinjiang.reflect01_class.Student");
Class c2 = Student.class;
利用 Object 对象的 getClass() 方法获取对象对应类的 Class 对象
Student stu = new Student();
Class c3 = stu.getClass();

| 方法 | 说明 |
|---|---|
| Constructor[] getConstructors() | 返回所有公共构造器对象的数组 |
| Constructor[] getDeclaredConstructors() | 返回所有构造器对象的数组,存在就能拿到 |
| Constructor getConstructor(Class… parameterTypes) | 返回指定的公共构造器对象 |
| Constructor getDeclaredConstructor(Class… parameterTypes) | 返回指定的构造器对象,存在就能拿到 |
| 方法 | 说明 |
|---|---|
| T newInstance(Object… initargs) | 根据执行的构造器创建对象 |
| void setAccessible(boolean flag) | 设置为true,表示取消访问检查,进行暴力反射 |
首先创建 Student 类对象
public class Student {
private String name;
private int age;
private Student() {
System.out.println("无参构造器执行");
}
private Student(String name){
this.name = name;
System.out.println("有参构造器执行");
}
public Student(String name, int age) {
this.name = name;
this.age = age;
System.out.println("全参构造器执行");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
测试获取构造器方法
import org.junit.Test;
import java.lang.reflect.Constructor;
public class TestConstructor01 {
// 1.getConstructors
@Test
public void testGetConstructors() {
// 1.获取类对象
Class c = Student.class;
// 2.获取所有类对象的公共构造器
Constructor[] constructors = c.getConstructors();
// 3.遍历
for (Constructor constructor : constructors) {
System.out.println(constructor.getName() + "===>" + constructor.getParameterCount());
}
}
// 2.getDeclaredConstructors
@Test
public void testGetDeclaredConstructors() {
// 1.获取类对象
Class c = Student.class;
// 2.获取所有类对象的构造器
Constructor[] constructors = c.getDeclaredConstructors();
// 3.遍历
for (Constructor constructor : constructors) {
System.out.println(constructor.getName() + "===>" + constructor.getParameterCount());
}
}
// 3.getConstructor(Class>... parameterTypes)
@Test
public void testGetConstructor() throws Exception {
// 1.获取类对象
Class c = Student.class;
// 2.获取所有类对象的构造器
Constructor constructor = c.getConstructor(String.class, int.class);
// 3.输出
System.out.println(constructor.getName() + "===>" + constructor.getParameterCount());
}
// 4.getDeclaredConstructor(Class>... parameterTypes)
@Test
public void testGetDeclaredConstructor() throws Exception {
// 1.获取类对象
Class c = Student.class;
// 2.获取所有类对象的构造器
Constructor constructor = c.getDeclaredConstructor();
// 3.输出
System.out.println(constructor.getName() + "===>" + constructor.getParameterCount());
}
}
测试使用构器创建对象方法
import org.junit.Test;
import java.lang.reflect.Constructor;
public class TestConstructor02 {
// 1.T newInstance(Object... initargs)
@Test
public void testNewInstance() throws Exception {
// 1.获取类对象
Class c = Student.class;
// 2.获取Student(String name)构造器,并以此创建对象
Constructor c01 = c.getDeclaredConstructor(String.class);
c01.setAccessible(true); // 暴力反射
Student stu01 = (Student) c01.newInstance("张三");
System.out.println(stu01);
// 3.获取Student(String name, int age)构造器,并以此创建对象
Constructor c02 = c.getDeclaredConstructor(String.class,int.class);
Student stu02 = (Student) c02.newInstance("李四",27);
System.out.println(stu02);
}
}

| 方法 | 说明 |
|---|---|
| Field[] getFields() | 返回所有公共成员变量对象的数组 |
| Field[] getDeclaredFields() | 返回所有成员变量对象的数组,存在就能拿到 |
| Field getField(String name) | 返回指定公共成员变量对象 |
| Field getDeclaredField(String name) | 返回指定成员变量对象,存在就能拿到 |
| 方法 | 说明 |
|---|---|
| void set(Object obj, Object value) | 给指定对象的此成员变量设置指定的新值 |
| Object get(Object obj) | 获取指定对象的该成员变量的值 |
| void setAccessible(boolean flag) | 暴力反射,设置为true可以直接访问私有属性的变量 |
| Class getType() | 获取变量的类型,返回类型Class对象 |
| String getName() | 获取变量的名称 |
首先创建 Student 类对象
public class Student {
private String name;
private int age;
public static String school;
public static final String COUNTRY = "中国";
public Student() {
}
private Student(String name) {
this.name = name;
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
测试获取成员变量的方法
import org.junit.Test;
import java.lang.reflect.Field;
public class TestField01 {
// 1.getFields()
// 2.getDeclaredFields()
@Test
public void testGetDeclaredFields() {
// 1.获取 class 对象
Class c = Student.class;
// 2.获取公共成员变量数组
Field[] fields = c.getDeclaredFields();
// 3.遍历
for (Field field : fields) {
System.out.println(field.getName() + "===>" + field.getType());
}
}
// 3.getField(String name)
// 4.getDeclaredField(String name)
@Test
public void testGetDeclaredField() throws Exception {
// 1.获取 class 对象
Class c = Student.class;
// 2.获取公共成员变量数组
Field field = c.getDeclaredField("age");
// 3.输出
System.out.println(field.getName() + "===>" + field.getType());
}
}
测试成员变量的赋值和取值方法
import org.junit.Test;
import java.lang.reflect.Field;
public class TestField02 {
@Test
public void testSetField() throws Exception {
// 1.获取class对象
Class c = Student.class;
// 2.获取指定成员变量
Field field = c.getDeclaredField("age");
field.setAccessible(true);
// 3.赋值
Student stu01 = new Student();
field.set(stu01, 18);
System.out.println(stu01);
// 4.取值
Student stu02 = new Student("李四", 27);
int age = (int) field.get(stu02);
System.out.println(age);
}
}

| 方法 | 说明 |
|---|---|
| Method[] getMethods() | 返回所有公共成员方法对象的数组 |
| Method[] getDeclaredMethods() | 返回所有成员方法对象的数组,存在就能拿到 |
| Method getMethod(String name, Class… parameterTypes) | 返回指定公共成员方法对象 |
| Method getDeclaredMethod(String name, Class… parameterTypes) | 返回指定成员方法对象,存在就能拿到 |
| 方法 | 说明 |
|---|---|
| Object invoke(Object obj, Object… args) | 运行方法 参数一:用obj对象调用该方法 参数二:调用方法传递的参数(如果没有就不写) 返回值:方法的返回值(如果没有就不写) |
| void setAccessible(boolean flag) | 暴力反射,设置为true可以直接调用私有方法运行 |
首先创建 Dog 类对象
public class Dog {
private String name;
public Dog() {
}
public Dog(String name) {
this.name = name;
}
public void run() {
System.out.println("小狗跑的飞快");
}
private void eat() {
System.out.println("狗吃骨头");
}
private String eat(String name) {
System.out.println("狗在吃" + name);
return "吃的很开心";
}
public static void inAddr() {
System.out.println("在上海有一只单身狗");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
测试获取成员方法的方法以及测试方法运行的方法
import org.junit.Test;
import java.lang.reflect.Method;
public class TestMethod01 {
// 1.getMethods()
// 2.getDeclaredMethods()
@Test
public void testGetDeclaredMethods() {
// 1.获取 class 对象
Class c = Dog.class;
// 2.获取成员方法数组
Method[] methods = c.getDeclaredMethods();
// 3.遍历
for (Method method : methods) {
System.out.println(method.getName() + " 返回值类型" + method.getReturnType() + " 参数个数" + method.getParameterCount());
}
}
// 3.getMethod(String name, Class>... parameterTypes)
// 4.getDeclaredMethod(String name, Class>... parameterTypes)
@Test
public void testGetDeclaredMethod() throws Exception {
// 1.获取 class 对象
Class c = Dog.class;
// 2.获取成员方法数组
Method method01 = c.getDeclaredMethod("eat");
method01.setAccessible(true);
Method method02 = c.getDeclaredMethod("eat",String.class);
method02.setAccessible(true);
// 3.执行方法
Dog dog = new Dog();
Object res01 = method01.invoke(dog);
Object res02 = method02.invoke(dog, "稀饭");
System.out.println(res01);
System.out.println(res02);
}
}
反射是作用在运行时的技术,此时集合的泛型将不能再产生约束了,此时是可以为集合存入其他任意类型的元素的

泛型只是在编译阶段可以约束集合只能操作某种数据类型,在编译成 Class 文件进入运行阶段的时候,其真实类型都是 ArrayList 了,泛型相当于被擦除了
代码如下:
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
public class ReflectDemo {
public static void main(String[] args) throws Exception {
List<String> list01 = new ArrayList<>();
List<Integer> list02 = new ArrayList<>();
System.out.println(list01.getClass());
System.out.println(list02.getClass());
System.out.println(list01.getClass() == list02.getClass()); // ArrayList.class
System.out.println("==============================");
List<Integer> list03 = new ArrayList<>();
list03.add(100);
list03.add(200);
// list03.add("三百");
// 1.获取class对象
Class c = list03.getClass();
// 2.获取指定method
Method method = c.getMethod("add",Object.class);
// 3.运行该方法
boolean b = (boolean) method.invoke(list03, "三百");
System.out.println(b);
System.out.println(list03);
System.out.println("==============================");
List list04 = list03;
list04.add("四百");
list04.add(true);
System.out.println(list03);
}
}
需求:给任意一个对象,在不清楚对象字段的情况下,可以把对象的字段名称和对应值存储到文件中去
分析:
创建 Student、Teacher 类
public class Student {
private String name;
private char sex;
private int age;
private String classroom;
private String hobby;
public Student() {
}
public Student(String name, char sex, int age, String classroom, String hobby) {
this.name = name;
this.sex = sex;
this.age = age;
this.classroom = classroom;
this.hobby = hobby;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getClassroom() {
return classroom;
}
public void setClassroom(String classroom) {
this.classroom = classroom;
}
public String getHobby() {
return hobby;
}
public void setHobby(String hobby) {
this.hobby = hobby;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", sex=" + sex +
", age=" + age +
", classroom='" + classroom + '\'' +
", hobby='" + hobby + '\'' +
'}';
}
}
public class Teacher {
private String name;
private char sex;
private double salary;
public Teacher() {
}
public Teacher(String name, char sex, double salary) {
this.name = name;
this.sex = sex;
this.salary = salary;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
@Override
public String toString() {
return "Teacher{" +
"name='" + name + '\'' +
", sex=" + sex +
", salary=" + salary +
'}';
}
}
创建工具类
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class MybatisUtil {
/**
* 保存任意类型的对象
*/
public static void save(Object obj) {
try {
PrintStream ps = new PrintStream(new FileOutputStream(
"P02_Reflect/src/com/lijinjiang/reflect06_framework/data.txt", true));
// 1.获取class对象
Class c = obj.getClass(); // c.getSimpleName() 获取当前类名 c.getName() 获取全限名:包名+类名
String simpleName = c.getSimpleName();
ps.println("===============" + simpleName + "===============");
// 2.获取全部成员变量
Field[] fields = c.getDeclaredFields();
// 3.获取成员变量的值
for (Field field : fields) {
field.setAccessible(true);
String name = field.getName();
String value = field.get(obj) + "";
ps.println(name + "=" + value);
}
ps.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
创建测试类
public class ReflectDemo {
public static void main(String[] args) {
Teacher teacher01 = new Teacher("古越涛", '男', 3999.9);
Teacher teacher02 = new Teacher("裴佩", '女', 4999.0);
Student student = new Student("蓝菲琳", '女', 18, "三年八班", "唱歌、跳舞");
MybatisUtil.save(teacher01);
MybatisUtil.save(teacher02);
MybatisUtil.save(student);
}
}
