1.快速入门

1.案例引入

image-20240114103703457

2.代码实例
package Reflection_;

import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;

/**
 * @author 孙显圣
 * @version 1.0
 */
public class ReflectionQuestion {
    public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        //使用反射来根据配置文件来调用方法

        //1.读取配置文件,获取类的全路径和方法
        Properties properties = new Properties();
        properties.load(new FileInputStream("src\\cat.properties"));
        String fullclasspath = properties.getProperty("fullclasspath");
        String method = properties.getProperty("method");

        //2.加载类,返回Class类型的对象cls
        Class<?> cls = Class.forName(fullclasspath);
        //3.获取加载类的对象实例
        Object o = cls.newInstance();
        //4.获取加载类的方法对象
        Method method1 = cls.getMethod(method);
        //5.调用这个方法
        method1.invoke(o);
    }
}

image-20240114103811437

3.反射机制原理图

image-20240114105523348

2.反射相关类

image-20240114142658917

1.反射获取类的成员
代码实例
package Reflection_;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * @author 孙显圣
 * @version 1.0
 */
public class Refection01 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
        //类加载,获取Class类型
        Class<?> cls = Class.forName("Reflection_.Cat");
        //反射获取属性
        Field name = cls.getField("name"); //不能获取私有的
        System.out.println(name);
        //反射获取构造器
        Constructor<?> constructor = cls.getConstructor(String.class);
        System.out.println(constructor);
        //反射获取方法
        Method hi = cls.getMethod("hi");
        System.out.println(hi);
    }
}

结果

image-20240114142738106

2.反射调用优化
1.关闭访问检查
  1. Method,Field,Constructor对象都有setAccessible方法
  2. setAccessible作用是启动和禁用访问安全检查的开关,true为取消
2.代码实例
package Reflection_;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * @author 孙显圣
 * @version 1.0
 */
public class Refection02 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
        //传统方法来调用hi
        new Cat().hi();

        //使用反射来调用hi
        Class<?> cls = Class.forName("Reflection_.Cat");
        //获取方法对象
        Method hi = cls.getMethod("hi");
        //获取加载类的对象实例
        Object o = cls.newInstance();
        //关闭访问检查,提高速度
        hi.setAccessible(true);
        //执行方法
        hi.invoke(o);
    }
}

3.Class类

1.类图

image-20240114144708984

2.基本介绍

image-20240114150034519

  1. Class也是类,因此也继承Object类
  2. Class类对象不是new出来的,而是系统创建的
  3. 对于某个类的Class类对象,在内存中只有一份,因为类只加载一次
  4. 每个类的实例都会记得自己是由哪个Class实例所生成的
  5. 通过Class对象,可以完整地得到一个类的完整结构,通过一系列API
  6. Class类对象是放在堆的,可以理解为是把方法区中的元数据保存到Class类对象中,方便获取其中的成员
  7. 类的字节码二进制数据,是放在方法区的,有的地方称为类的元数据
3.Class类常用方法
代码实例
package Reflection_;

import java.lang.reflect.Field;

/**
 * @author 孙显圣
 * @version 1.0
 */
public class Class01 {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException {
        //定义全路径
        String allClassPath = "Reflection_.Cat";
        //获取Cat类的Class类对象
        Class<?> cls = Class.forName(allClassPath);
        //显示该对象是哪个类的Class对象
        System.out.println(cls);
        //显示运行类型
        System.out.println(cls.getClass());
        //获取包名
        System.out.println(cls.getPackage().getName());
        //获取全类名
        System.out.println(cls.getName());
        //通过反射创建对象
        Cat o = (Cat) cls.newInstance();
        o.hi(); //调用Cat类的方法
        //通过反射获取属性
        Field name = cls.getField("name");
        //通过反射给属性赋值
        name.set(o,"小猫");
        System.out.println(name.get(o));
        //遍历所有属性
        Field[] fields = cls.getFields();
        for (Field field : fields) {
            System.out.println(field.get(o));
        }

    }
}

结果

image-20240114152919844

4.获取Class类对象
代码实例
package Reflection_;

/**
 * @author 孙显圣
 * @version 1.0
 */
public class Class02 {
    public static void main(String[] args) throws Exception {
        //获取反射对象的六种方式
        //1. Class.forName
        String classAllPath = "Reflection_.Cat"; //一般通过读取配置文件获取,在框架中用的较多
        Class<?> aClass = Class.forName(classAllPath);
        //2. 类名.class,应用场景:用于参数传递
        System.out.println(Cat.class);
        //3. 对象.getClass(),应用场景:有对象实例,获取运行类型
        System.out.println(new Cat().getClass());
        //4. 通过类加载器获取
        ClassLoader classLoader = Cat.class.getClassLoader(); //获取类加载器
        Class<?> aClass1 = classLoader.loadClass(classAllPath);

        //5.基本数据类型 类型.class
        Class<Integer> integerClass = int.class;
        Class<Character> characterClass = char.class;
        System.out.println(integerClass);
        System.out.println(characterClass);

        //6.基本数据类型对应的包装类 类型.TYPE
        Class<Integer> type = Integer.TYPE;
        Class<Character> type1 = Character.TYPE;
        System.out.println(type);
        System.out.println(type1);
    }
}

结果

image-20240114155716147

5.哪些类型有Class对象

image-20240114160053097

4.类加载

1.基本介绍
  1. 静态加载:编译时加载相关的类,如果没有则报错
  2. 动态加载:运行时才加载需要的类,如果运行时不使用该类,即使不存在该类,则不报错,降低了依赖性
  3. 类加载时机:
    1. 当创建对象时
    2. 当子类被加载时,父类也会被加载
    3. 调用类中的静态成员时
    4. 通过反射(动态加载)
2.静态加载与动态加载实例

在这里如果没有Dog类则直接编译报错,但是如果没有Person类,只要不执行case2则不会报错

3.类加载流程图

image-20240114164018137

image-20240114164159830

image-20240114164548582

image-20240114165345356

image-20240114165352321

image-20240114165618491

image-20240114170514602

4.简要理解类加载
  1. 加载:得到Class类对象
  2. 连接:静态默认初始化,常量直接初始化
  3. 合并初始化:将静态代码合并,根据语句内容进行初始化

5.反射获取类的结构信息

第一组

image-20240114185352788

代码实例
package Reflection_;

import org.junit.jupiter.api.Test;

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * @author 孙显圣
 * @version 1.0
 */
public class ReflectionUtils {
    public static void main(String[] args) {

    }
    @Test
    public void api_01() throws Exception {
        //得到Class对象
        Class<?> personCls = Class.forName("Reflection_.Person");
        // getName:获取全类名
        System.out.println(personCls.getName());
        // getSimpleName:获取简单类名
        System.out.println(personCls.getSimpleName());
        // getFields:获取所有public修饰的属性,包含父类以及本类的
        Field[] fields = personCls.getFields();
        for (Field field : fields) {
            System.out.println(field);
        }
        // getDeclaredFields:获取本类所有属性
        Field[] declaredFields = personCls.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println("本类所有属性:" + declaredField);
        }
        // getMethods:获取所有public修饰的方法,包括本类以及父类的
        Method[] methods = personCls.getMethods();
        for (Method method : methods) {
            System.out.println(method);
        }
        // getDeclaredMethods:获取本类所有方法
        Method[] declaredMethods = personCls.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println("本类所有方法:" + declaredMethod);
        }
        // getConstructors: 获取所有public修饰的构造器,包括本类的
        Constructor<?>[] constructors = personCls.getConstructors();
        for (Constructor<?> constructor : constructors) {
            System.out.println(constructor);
        }
        // getDeclaredConstructors: 获取本类所有的构造器
        Constructor<?>[] declaredConstructors = personCls.getDeclaredConstructors();
        System.out.println("本类所有构造器:" +declaredConstructors);
        // getPackage:以Package形式返回包信息
        System.out.println(personCls.getPackage());
        // getSuperClass:以Class形式返回父类信息
        System.out.println(personCls.getSuperclass());
        // getInterfaces:以Class[]形式返回接口信息
        Class<?>[] interfaces = personCls.getInterfaces();
        for (Class<?> anInterface : interfaces) {
            System.out.println("所有接口信息:" + anInterface);
        }
        // getAnnotations:以Annotation[]形式返回注解信息
        Annotation[] annotations = personCls.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println(annotation);
        }
    }
}
interface B {

}
class A {
    public String hobby;
    public void hi() {

    }

}
@SuppressWarnings("all")
@Deprecated
class Person extends A implements B{
    //属性
    public String name;
    protected int age;
    String job;
    private double sal;

    //构造器

    //方法
    public void m1() {

    }
    protected void m2() {

    }
    void m3() {

    }
    private void m4() {

    }
}
结果

image-20240114183919690

第二组

image-20240114185417447

代码实例
    @Test
    public void api_02() throws ClassNotFoundException {
        //得到Class对象
        Class<?> personCls = Class.forName("Reflection_.Person");
        Field[] declaredFields = personCls.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println("该类的字段名:" + declaredField.getName() +
                    " 该类的修饰符int形式:" +declaredField.getModifiers() +
                    " 该类的Class类型:" + declaredField.getType());
        }
    }
结果

image-20240114185948128

第三组

image-20240114190016983

代码实例
    @Test
    public void api_03() throws ClassNotFoundException {
        //得到Class对象
        Class<?> personCls = Class.forName("Reflection_.Person");
        Method[] declaredMethods = personCls.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println("该类的方法名:" + declaredMethod.getName() +
                    " 该类的方法修饰符int形式:" +declaredMethod.getModifiers() +
                    " 该类的方法返回类型:" + declaredMethod.getReturnType());
            //获取参数类型数组
            Class<?>[] parameterTypes = declaredMethod.getParameterTypes();
            for (Class<?> parameterType : parameterTypes) {
                System.out.println("参数类型:" + parameterType);
            }
        }

    }
结果

image-20240114190556792

第四组

image-20240114190633447

代码实例
    @Test
    public void api_04() throws ClassNotFoundException {
        //得到Class对象
        Class<?> personCls = Class.forName("Reflection_.Person");
        Constructor<?>[] declaredConstructors = personCls.getDeclaredConstructors();
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            System.out.println("该类的构造器名:" + declaredConstructor.getName() +
                    " 该类的构造器int形式修饰符:" + declaredConstructor.getModifiers()
                    );
            Class<?>[] parameterTypes = declaredConstructor.getParameterTypes();
            for (Class<?> parameterType : parameterTypes) {
                System.out.println("参数类型:" + parameterType);
            }
        }

    }
结果

image-20240114191126368

6.反射爆破

1.反射爆破创建实例

image-20240114191310545

代码实例
package Reflection_;

import java.lang.reflect.Constructor;

/**
 * @author 孙显圣
 * @version 1.0
 */
public class CreateInstance {
    public static void main(String[] args) throws Exception {
        //获取Class类对象
        Class<?> userClass = Class.forName("Reflection_.User");
        //1.使用无参构造方法创建实例
        Object o = userClass.newInstance();
        System.out.println(o);
        //2.使用public的有参构造方法创建实例
        //获取有参构造器对象
        Constructor<?> constructor = userClass.getConstructor(String.class);
        //创建实例
        Object o1 = constructor.newInstance("小明");
        System.out.println(o1);
        //3.使用非public的有参构造方法创建实例
        //获取构造器
        Constructor<?> declaredConstructor = userClass.getDeclaredConstructor(String.class, int.class);
        //反射爆破
        declaredConstructor.setAccessible(true);
        //创建实例
        Object o2 = declaredConstructor.newInstance("杰克", 20);
        System.out.println(o2);
    }
}
class User {
    private String name = "李华";
    private int age = 18;
    public User() {

    }

    public User(String name) {
        this.name = name;
    }

    private User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

结果

image-20240114193242314

2.反射爆破操作属性

image-20240114193444582

代码实例
package Reflection_;

import java.lang.reflect.Field;

/**
 * @author 孙显圣
 * @version 1.0
 */
public class AccessProperty {
    public static void main(String[] args) throws Exception {
        //获取Class实例
        Class<Student> studentClass = Student.class;
        //反射创建一个实例
        Student student = studentClass.newInstance();

        //1.操作public的属性
        //获取public的属性
        Field age = studentClass.getField("age");
        //操作
        age.set(student, 100);
        System.out.println(age.get(student));

        //2.操作非public且静态的属性
        //获取私有属性
        Field name = studentClass.getDeclaredField("name");
        //反射爆破
        name.setAccessible(true);
        //操作
        name.set(null, "李华");
        System.out.println(name.get(null)); //注意这里是因为是静态的属性才能填null,如果不是静态的则必须填对象
    }
}
class Student {
    public int age;
    private static String name;

    @Override
    public String toString() {
        return "Student{" +
                "age=" + age +
                '}';
    }
}
结果

image-20240114195123147

3.反射爆破操作方法

image-20240114195340807

代码实例
package Reflection_;

import java.lang.reflect.Method;

/**
 * @author 孙显圣
 * @version 1.0
 */
public class AccessMethod {
    public static void main(String[] args) throws Exception {
        //获取Class对象
        Class<Boss> bossClass = Boss.class;
        //创建实例
        Boss boss = bossClass.newInstance();

        //1.操作public的方法
        //获取方法
        Method hi = bossClass.getMethod("hi", String.class);
        //操作
        hi.invoke(boss, "李华");

        //2.操作非public的方法
        //获取方法
        Method say = bossClass.getDeclaredMethod("say", int.class, String.class, char.class);
        //爆破
        say.setAccessible(true);
        //操作
        Object invoke = say.invoke(null, 1, "2", '3');//注意,因为这里是静态的方法所以才能是null
        System.out.println(invoke);
    }
}

class Boss {
    public int age;
    private static String name;

    private static String say(int n, String s, char c) {
        return n + "" + s + "" + c;
    }

    public void hi(String s) {
        System.out.println("hi:" + s);
    }
}

结果

image-20240114200437193

7.本章练习

练习一
题目

image-20240114200549768

代码
package Reflection_;

import java.lang.reflect.Field;

/**
 * @author 孙显圣
 * @version 1.0
 */
public class HomeWork01 {
    public static void main(String[] args) throws Exception{
        //获取Class类
        Class<PrivateTest> privateTestClass = PrivateTest.class;
        //创建实例
        PrivateTest privateTest = privateTestClass.newInstance();
        //获取属性
        Field name = privateTestClass.getDeclaredField("name");
        //反射爆破
        name.setAccessible(true);
        //修改属性
        name.set(privateTest, "cat");
        //输出属性
        System.out.println(name.get(privateTest));
    }
}

class PrivateTest {
    private String name = "hellokitty";

    public String getName() {
        return name;
    }
}

结果

image-20240114201101007

练习二
题目

image-20240114201155350

代码
package Reflection_;

import java.io.File;
import java.lang.reflect.Constructor;

/**
 * @author 孙显圣
 * @version 1.0
 */
public class HomeWork02 {
    public static void main(String[] args) throws Exception{
        //获取File类的Class对象
        Class<File> fileClass = File.class;
        //打印所有构造器
        Constructor<?>[] declaredConstructors = fileClass.getDeclaredConstructors();
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            System.out.println(declaredConstructor);
        }
        //获取构造器
        Constructor<File> declaredConstructor = fileClass.getDeclaredConstructor(String.class);
        //创建实例
        File file = declaredConstructor.newInstance("src\\Reflection_\\a.txt");
        file.createNewFile();
    }
}

结果

image-20240114201737033

Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐