Java核心API-反射

反射


文章目录

  • 反射
  • 前言
  • 一、反射概念
  • 二、反射与Class类
    • 获取Class对象方式
  • 三、反射访问构造方法
    • 1、获取包名
    • 2、获取类名
    • 3、获取父类名称
    • 4、获取接口
    • 5、获取类中构造方法
      • 1)获取所有的构造方法
      • 2)获取public修饰的构造方法
      • 3)获取private修饰的构造方法
      • 4)获取无参构造方法
      • 5)获取有参构造方法
  • 四、反射访问成员变量
    • 1、访问所有的成员变量
    • 2、访问特定的成员变量
    • 3、访问公共的成员变量
    • 4、访问私有的成员变量
  • 五、反射访问成员方法
    • 1、获取类中所有的成员方法
    • 2、类中所有public修饰的方法
    • 3、获取并调用无参方法
    • 4、获取并调用有参方法
    • 5、获取并调用私有方法


前言

在计算机学科中,反射是指计算机程序在运行时可以访问、检测和修改它本身状态或行为的一种能力。通过Java的反射机制,程序员可以更深入地控制程序的运行过程,如在程序运行时对用户输入的信息进行验证,还可以逆向控制程序的执行过程。理解反射机制是学习Spring框架的基础。


一、反射概念

1)Java的反射机制是一种动态获取信息以及动态调用对象的方法的功能

2)具体来说,在程序运行时,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性

3)通过Java反射机制,就可以在程序中访问已经装载到JVM中的Java对象的各种描述,能够访问、检测和修改描述Java对象本身信息

4)Java在java.lang.reflect包中提供了对该功能的支持

二、反射与Class类

1)反射与Class类息息相关。Class对象封装了它所代表的类的描述信息,通过调用Class对象的各种方法,就可以获取到Class对象所代表的类的主要描述信息

2)获取目标类的Class对象,有以下3种方法可以实现

​ 使用Object类的getClass()方法

​ 使用Class类的forName(String url)方法,用目标类的完整路径作为参数

​ 使用目标类的class属性

/*
例如现在有一个Student类,类中有属性、构造方法、普通方法等等
现在把Student类中的内容存储到Class类对象中,既然是对象就可以通过方法获取里面的内容
*/
/*
public final Class<?> getClass()返回此 Object 的运行时类
*/
/*
public static Class<?> forName(String className)throws ClassNotFoundException
返回与带有给定字符串名的类或接口相关联的 Class 对象
*/
public class Person {

    // 公共属性
    public String name;
    // 私有属性
    private int age;

    // 无参构造
    public Person() {
        this.name = "张三";
        this.age = 18;
    }

    // 有参构造
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // 私有有参构造
    private Person(String name) {
        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 "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    // 无参方法
    public void eat() {
        System.out.println("今天吃了1顿大餐");
    }

    // 有参方法
    public void eat(int num) {
        System.out.println("今天吃了" + num + "顿大餐");
    }

    // 私有方法
    private void sleep() {
        System.out.println("非常舒服的睡了一觉");

    }
}

获取Class对象方式

public class GetClassDemo01 {

    public static void main(String[] args) throws ClassNotFoundException {

        /*
        Person继承Object类
        public final Class<?> getClass()返回此 Object 的运行时类

        获取Class对象的方式一:使用Object类中的getClass()方法
        */
        Person person1 = new Person();
        Class personClass1 = person1.getClass();
        System.out.println("personClass1 : " + personClass1);

        /*
        public static Class<?> forName(String className)throws ClassNotFoundException
        返回与带有给定字符串名的类或接口相关联的 Class 对象

        获取Class对象的方式二:使用Class类中的forName(String className)方法
        注意:className必须是完整路径名
        */
        Class personClass2 = Class.forName("javaapidemo0219.entity.Person");
        System.out.println("personClass2 : " + personClass2);

        /*
        获取Class对象的方式三:使用Person类中默认存在的class属性(静态属性)
        */
        Class personClass3 = Person.class;
        System.out.println("personClass3 : " + personClass3);

        /*
        输出结果
        personClass1 : class javaapidemo0219.entity.Person
        personClass2 : class javaapidemo0219.entity.Person
        personClass3 : class javaapidemo0219.entity.Person
        */

        // 判断获取的Class对象是否是同一个对象
        System.out.println(personClass1 == personClass2); // true
        System.out.println(personClass2 == personClass3); // true

        /*
        说明:上面3种方式做的是同一件事,将Person类中的内容(属性、构造方法、成员方法)存储在Class类对象(就是一个容器)中
        然后就可以通过Class对象调用相关方法对Person类中的内容进行操作
        */

    }
}

三、反射访问构造方法

// 首先通过Class类中forName()方法将Person类装载到Class类对象中
        Class personClass = Class.forName("javaapidemo0219.entity.Person");

1、获取包名

首先调用Class类中getPackage()方法,返回值为Package类

然后调用Package类中getName()方法,返回值为String

// 获取Person类所在的包的名称
        // public Package getPackage()获取此类的包
        Package personClassPackage = personClass.getPackage();
        // String getName()返回此包的名称
        String personClassPackageName = personClassPackage.getName();
        System.out.println("包名 : " + personClassPackageName); // javaapidemo0219.entity

2、获取类名

直接调用Class类中getName()方法,返回值为String

// 获取加载的类的名称
        // String getName() 以String的形式返回此Class对象所表示的实体(类、接口、数组类、基本类型或void)名称
        String className = personClass.getName();
        System.out.println("类名 : " + className); // javaapidemo0219.entity.Person

3、获取父类名称

首先调用Class类中getSuperclass()方法,返回值为Class类

接着调用Class类中getName()方法,返回值为String

// 获取加载的类的父类
		/*
        public Class<? super T> getSuperclass()
		返回表示此 Class 所表示的实体(类、接口、基本类型或 void)的超类的 Class
		*/
        Class personClassSuperclass = personClass.getSuperclass();
        // 获取父类名
        String personClassSuperclassName = personClassSuperclass.getName();
        System.out.println("父类名称 :" + personClassSuperclassName); // java.lang.Object

4、获取接口

首先调用Class类中getInterfaces()方法,返回值是一个数组

(数组中接口对象顺序与此对象所表示的类的声明的 implements 子句中接口名顺序一致)

然后遍历数组使用getName()方法

// 获取加载的类实现的接口
        // Class<?>[] getInterfaces()确定此对象所表示的类或接口实现的接口
        Class[] personClassInterfaces = personClass.getInterfaces();
        // 遍历数组,获取所有实现的接口的名称
        for (Class clazz : personClassInterfaces) {
            System.out.println("实现的接口名称 :" + clazz.getName());
            // 实现的接口名称 :java.io.Serializable
        }

案例代码

public class ClassDemo01 {

    public static void main(String[] args) throws ClassNotFoundException {

        // 首先通过Class类中forName()方法将Person类装载到Class类对象中
        Class personClass = Class.forName("javaapidemo0219.entity.Person");

        // 获取Person类所在的包的名称
        // public Package getPackage()获取此类的包
        Package personClassPackage = personClass.getPackage();
        // String getName()返回此包的名称
        String personClassPackageName = personClassPackage.getName();
        System.out.println("包名 : " + personClassPackageName); // 包名 : javaapidemo0219.entity

        // 获取加载的类的名称
        // String getName() 以String的形式返回此Class对象所表示的实体(类、接口、数组类、基本类型或void)名称
        String className = personClass.getName();
        System.out.println("类名 : " + className); // 类名 : javaapidemo0219.entity.Person

        // 获取加载的类的父类
        // public Class<? super T> getSuperclass()返回表示此 Class 所表示的实体(类、接口、基本类型或 void)的超类的 Class
        Class personClassSuperclass = personClass.getSuperclass();
        // 获取父类名称
        String personClassSuperclassName = personClassSuperclass.getName();
        System.out.println("父类名称 :" + personClassSuperclassName); // 父类名称 :java.lang.Object

        // 获取加载的类实现的接口
        // Class<?>[] getInterfaces()确定此对象所表示的类或接口实现的接口
        Class[] personClassInterfaces = personClass.getInterfaces();
        // 遍历数组,获取所有实现的接口的名称
        for (Class clazz : personClassInterfaces) {
            System.out.println("实现的接口名称 :" + clazz.getName()); // 实现的接口名称 :java.io.Serializable
        }

    }
}

/*
包名 : javaapidemo0219.entity
类名 : javaapidemo0219.entity.Person
父类名称 :java.lang.Object
实现的接口名称 :java.io.Serializable
*/

5、获取类中构造方法

1)获取所有的构造方法

首先调用Class类中getDeclaredConstructors()方法,返回值为Constructor 对象数组

然后遍历数组,数组中的元素为Constructor类对象,调用方法获取构造方法修饰符、构造方法名、构造方法形参

在这里插入图片描述

// 使用Object类中的getClass()方法获取Class对象,将Person类加载到Class对象中
		Person person = new Person();
        Class personClass = person.getClass();

        // 获取所有构造方法,包括public、private修饰的构造方法
		/*
		public Constructor<?>[] getDeclaredConstructors()throws SecurityException
		返回 Constructor 对象的一个数组,这些对象反映此 Class 对象表示的类声明的所有构造方法
		它们是公共、保护、默认(包)访问和私有构造方法
		*/
        Constructor[] constructors = personClass.getDeclaredConstructors();
        // 遍历数组,输出数组中每一个构造方法的名称、访问修饰符、形参名称
        for (Constructor constructor : constructors) {
            
            // 获取构造方法名
            System.out.println("构造方法名:" + constructor.getName());
            
            // 获取构造方法的修饰符
            int num = constructor.getModifiers();
            System.out.println("\t构造方法修饰符:" + (num == 1 ? "public" : "private"));
            // public = 1 private = 2
            
            // 获取构造方法的形参名称
            /*
            public Class<?>[] getParameterTypes()
            按照声明顺序返回一组 Class 对象,这些对象表示此 Constructor 对象所表示构造方法的形参类型
            */
            Class[] types = constructor.getParameterTypes();
            for (Class type : types) {
                
                // 获取各个参数的名称
                System.out.println("\t构造方法形参名称:" + type.getName());
                
            }
        }
/*
构造方法名:javaapidemo0219.entity.Person
	构造方法修饰符:private
	构造方法形参名称:java.lang.String
构造方法名:javaapidemo0219.entity.Person
	构造方法修饰符:public
	构造方法形参名称:java.lang.String
	构造方法形参名称:int
构造方法名:javaapidemo0219.entity.Person
	构造方法修饰符:public
*/

2)获取public修饰的构造方法

首先调用Class类中getConstructors()方法,返回值为Constructor 对象数组

// 获取Person类中所有的public修饰的构造方法

		/*
		Constructor<?>[] getConstructors()
		返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对象所表示的类的所有公共构造方法
		*/
        Constructor[] personClassConstructors = personClass.getConstructors();
        // 遍历数组,输出所有构造方法的名称、访问修饰符
        for (Constructor constructor : personClassConstructors) {

            // 获取构造方法名
            String constructorName = constructor.getName();
            System.out.println("构造方法名 : " + constructorName);

            // 获取构造方法的修饰符
            int num = constructor.getModifiers();
            System.out.println("\t构造方法修饰符 : " + (num == 1 ? "public" : "private"));

            // 获取每个构造方法的形参列表
            /*
            public Class<?>[] getParameterTypes()
            按照声明顺序返回一组 Class 对象,这些对象表示此 Constructor 对象所表示构造方法的形参类型
            */
            Class[] parameterTypes = constructor.getParameterTypes();
            // 遍历数组,获取每个构造方法的形参名称
            for (Class type : parameterTypes) {
                System.out.println("\t形参名称 : " + type.getName());
            }
        }
/*
构造方法名 : javaapidemo0219.entity.Person
	构造方法修饰符 : public
	形参名称 : java.lang.String
	形参名称 : int
构造方法名 : javaapidemo0219.entity.Person
	构造方法修饰符 : public
*/

3)获取private修饰的构造方法

Class类中没有专门的方法返回私有的构造方法

可以获取所有的构造方法(getDeclaredConstructors()方法)进行判断

Person person = new Person();
        Class personClass = person.getClass();

        // Class类中方法
        Constructor[] constructors = personClass.getDeclaredConstructors();

        for (Constructor constructor : constructors) {

            // 获取构造方法的修饰符
            int num = constructor.getModifiers();
            if (num == 2) {
                // 获取构造方法名
                System.out.println("构造方法名:" + constructor.getName());
                //
                System.out.println("\t构造方法修饰符 : " + (num == 1 ? "public" : "private"));

                Class[] parameterTypes = constructor.getParameterTypes();
                // 遍历数组,获取每个构造方法的形参名称
                for (Class type : parameterTypes) {
                    System.out.println("\t形参名称 : " + type.getName());
                }
            }

        }
/*
构造方法名:javaapidemo0219.entity.Person
	构造方法修饰符 : private
	形参名称 : java.lang.String
*/

4)获取无参构造方法

Class类中的getConstructor()方法

然后使用newInstance()方法,Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例

// 使用Object类中的getClass()方法获取Class对象,将Person类加载到Class对象中
        Person person = new Person();
        Class personClass = person.getClass();

        // 获取Person类中的public修饰的无参构造方法

		/*
		public Constructor<T> getConstructor(Class<?>... parameterTypes)
		返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法
		*/
        Constructor personClassConstructor1 = personClass.getConstructor();
        // 通过personClassConstructor1对象调用方法,可以获取Person类中构造方法的相关信息

        // 获取构造方法的名称
        // String gertName()以字符串形式返回此构造方法的名称
        String personClassConstructor1Name = personClassConstructor1.getName();
        System.out.println("构造方法名 : " + personClassConstructor1Name);
		// 构造方法名 : javaapidemo0219.entity.Person

        // 获取构造方法的访问修饰符
        // public int getModifiers()返回此类或接口以整数编码的 Java 语言修饰符
        int num = personClassConstructor1.getModifiers();
        System.out.println(num == 1 ? "public" : "private"); // public
        // java.lang.reflect.Modifier public = 1 private = 2

		// 通过获取的无参构造方法创建对象
		/*
		public T newInstance(Object... initargs)
		使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例
		*/
        Person person1 = (Person)personClassConstructor1.newInstance();
        System.out.println("person1 : " + person1); // person1 : Person{name='张三', age=18}

5)获取有参构造方法

// 获取Person类中带有两个参数的public修饰的有参构造方法
        Constructor constructor = personClass.getConstructor(String.class,int.class);
        System.out.println(constructor);
		// public javaapidemo0219.entity.Person(java.lang.String,int)

        // 通过该构造方法创建对象
        Person person2 = (Person)constructor.newInstance("李二狗",21);
        System.out.println(person2); // Person{name='李二狗', age=21}

四、反射访问成员变量

1、访问所有的成员变量

包括public、private修饰的成员变量

调用Class类中的getDeclaredFields()方法,返回值为Field对象数组

在这里插入图片描述

import javaapidemo0219.entity.Person;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;

public class ClassDemo02 {

    public static void main(String[] args) throws NoSuchMethodException, ClassNotFoundException, InvocationTargetException, InstantiationException, IllegalAccessException {

        Class personClass = Class.forName("javaapidemo0219.entity.Person");

        //
        Constructor personClassConstructor = personClass.getConstructor(String.class, int.class);
        Person person = (Person) personClassConstructor.newInstance("牛", 24);

        // Field[] getDeclaredFields()返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段。
        Field[] personClassFields = personClass.getDeclaredFields();

        for (Field field : personClassFields) {
            // 输出属性名
            // String getName()返回此 Field 对象表示的字段的名称
            System.out.println("属性名 :" + field.getName());

            // 输出属性的数据类型
            // Class<?> getType()返回一个 Class 对象,它标识了此 Field 对象所表示字段的声明类型
            System.out.println("属性数据类型 :" + field.getType().getName());

            // 输出访问修饰符
            System.out.println("属性访问修饰符 :" + ((field.getModifiers() == 1) ? "public" : "private"));

            /*
            属性名 :name
            属性数据类型 :java.lang.String
            属性访问修饰符 :public
            属性名 :age
            属性数据类型 :int
            属性访问修饰符 :private
            */

            // 获取属性的值
            /*if (field.getType().equals(String.class)) {
                System.out.println(field.get(person));
            } else if (field.getType().equals(int.class)) {
                System.out.println(field.get(person));
            }*/ // 可以输出name属性值,无法获取private修饰的age属性值

            // 但是在反射中可以暴力破解
            if (field.getType().equals(String.class)) {
                System.out.println(field.get(person));
            } else if (field.getType().equals(int.class)) {
                // Person类中age属性被private修饰了,不能直接访问,需要进行暴力破解
                if (field.getModifiers() == Modifier.PRIVATE) {
                    /*
                    public void setAccessible(boolean flag)
                    将此对象的 accessible 标志设置为指示的布尔值。值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查
                    */
                    field.setAccessible(true);
                    System.out.println(field.get(person));
                }
            }
            /*
            属性名 :name
            属性数据类型 :java.lang.String
            属性访问修饰符 :public
            牛
            属性名 :age
            属性数据类型 :int
            属性访问修饰符 :private
            24
            */

        }

    }
}

2、访问特定的成员变量

调用Class类中getField()方法,返回Field对象

import javaapidemo0219.entity.Person;

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

public class ClassDemo03 {

    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {

        Class personClass = Class.forName("javaapidemo0219.entity.Person");

        // 获取特定的属性值并修改

        // 创建一个Person类对象,需要通过构造方法
        Constructor personClassConstructor  =personClass.getConstructor(String.class,int.class);
        Person person =(Person)personClassConstructor.newInstance("王五",22);

        // 获取Person类中指定的属性
        /*
        public Field getField(String name)throws NoSuchFieldException,SecurityException
        返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段
        */
        Field nameField = personClass.getField("name");
        System.out.println(nameField.getName()+"-"+nameField.getType().getName()+"-"+nameField.getModifiers());
        // public Object get(Object obj)返回指定对象上此 Field 表示的字段的值
        System.out.println(nameField.get(person));
        // 
        nameField.set(person,"李二狗");

        Field ageField =personClass.getDeclaredField("age");
        // 
        ageField.setAccessible(true);
        System.out.println(ageField.get(person));
        ageField.set(person,33);

        System.out.println(person);
        

    }
}
/*
name-java.lang.String-1
王五
22
Person{name='李二狗', age=33}
*/

3、访问公共的成员变量

调用Class类中getFields()方法获取Class 对象所表示的类或接口的所有可访问公共字段

import java.lang.reflect.Field;

public class ClassDemo01 {

    public static void main(String[] args) throws ClassNotFoundException {

        Class personClass = Class.forName("javaapidemo0219.entity.Person");

        // 获取Person类中的成员变量(public修饰的成员变量)

        /*
        public Field[] getFields()throws SecurityException
        返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段
        */
        Field[] personClassFields = personClass.getFields();
        // 遍历数组,获取数组中每一个字段的访问修饰符、数据类型、属性名
        for (Field field : personClassFields) {
            // 输出属性名
            // String getName()返回此 Field 对象表示的字段的名称
            System.out.println("属性名 :" + field.getName());

            // 输出属性的数据类型
            // Class<?> getType()返回一个 Class 对象,它标识了此 Field 对象所表示字段的声明类型
            System.out.println("属性数据类型 :" + field.getType().getName());

            // 输出访问修饰符
            System.out.println("属性访问修饰符 :" + ((field.getModifiers() == 1) ? "public" : "private"));
        }

    }
}

4、访问私有的成员变量

getDeclaredField(String name)方法

// 访问私有成员变量的属性值和修改属性值需要暴力破解

五、反射访问成员方法

1、获取类中所有的成员方法

包括public、private修饰的方法,但不包括父类的方法

调用Class类中getDeclaredMethods()方法

// 通过反射获取Person类中所有public修饰的方法(获得所有方法,包括private修饰的方法,但不包括父类的方法)
        Method[] personClassMethods = personClass.getDeclaredMethods();

2、类中所有public修饰的方法

类中所有public修饰的方法,包括父类中public修饰的方法

调用Class类中getMethods()方法

// 通过反射获取Person类中所有public修饰的方法(包括父类Object类中public修饰的方法)
        Method[] personClassMethods = personClass.getMethods();

3、获取并调用无参方法

调用Class类中getMethod(String name)方法

// 通过反射获取Person类中的无参eat()方法
        Method eatMethod1 = personClass.getMethod("eat");
		// 调用获取的这个eat方法
		/*
		public Object invoke(Object obj,Object... args)throws IllegalAccessException,IllegalArgumentException,InvocationTargetException
		对带有指定参数的指定对象调用由此 Method 对象表示的底层方法
		*/
        eatMethod1.invoke(person);//等价与person.eat();

4、获取并调用有参方法

调用Class类中getMethod(String name, Class)方法

// 通过反射获取Person了中的有参eat()方法
        Method eatMethod2 = personClass.getMethod("eat", int.class);
        // 调用获取的这个eat方法
        eatMethod2.invoke(person, 3); // 等价与person.eat(3); 参数

5、获取并调用私有方法

调用Class类中getDeclaredMethod(String name)方法

// 通过反射获取Person类中的sleep()方法
        Method sleepMethod1 = personClass.getDeclaredMethod("sleep");
        // sleepMethod1.invoke(person);//IllegalAccessException
        // 暴力破解私有方法(跳过访问修饰符的检查)
        sleepMethod1.setAccessible(true);
        sleepMethod1.invoke(person);
import javaapidemo0219.entity.Person;

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

public class ClassDemo04 {

    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {

        // 使用Person类中默认的class属性获取Class对象
        Class personClass = Person.class;
        // 使用无参构造创建一个Person类对象
        Person person = new Person();
        System.out.println(person);

        System.out.println ("------ ------ ------");

        // 通过反射获取Person类中所有public修饰的方法(包括父类Object类中public修饰的方法)
        // Method[] personClassMethods = personClass.getMethods();

        // 通过反射获取Person类中所有public修饰的方法(获得所有方法,包括private修饰的方法,但不包括父类的方法)
        Method[] personClassMethods = personClass.getDeclaredMethods();

        for (Method method : personClassMethods) {
            // 获取方法名称
            System.out.println("方法名:" + method.getName());
            // 获取方法返回值
            System.out.println("\t方法返回值类型:" + method.getReturnType().getName());
            // 获取方法的参数列表
            Class[] methodParameterTypes = method.getParameterTypes();
            // 遍历数组,获取每个方法的形参列表名称
            for (Class type : methodParameterTypes) {
                System.out.println("\t参数名:" + type.getName());
            }
            // 获取方法的访问修饰符
            System.out.println("\t方法修饰符:" + method.getModifiers());
        }

        System.out.println("------------------------------------------------");

        // 通过反射获取Person类中的无参eat()方法
        Method eatMethod1 = personClass.getMethod("eat");
        // 调用获取的这个eat方法
        eatMethod1.invoke(person);//等价与person.eat();

        // 通过反射获取Person了中的有参eat()方法
        Method eatMethod2 = personClass.getMethod("eat", int.class);
        // 调用获取的这个eat方法
        eatMethod2.invoke(person, 3); // 等价与person.eat(3);

        // 通过反射获取Person类中的sleep()方法
        Method sleepMethod1 = personClass.getDeclaredMethod("sleep");
        // sleepMethod1.invoke(person); // IllegalAccessException
        // 暴力破解私有方法(跳过访问修饰符的检查)
        sleepMethod1.setAccessible(true);
        sleepMethod1.invoke(person);

    }
}

/*
Person{name='张三', age=18}
------ ------ ------
方法名:toString
	方法返回值类型:java.lang.String
	方法修饰符:1
方法名:getName
	方法返回值类型:java.lang.String
	方法修饰符:1
方法名:setName
	方法返回值类型:void
	参数名:java.lang.String
	方法修饰符:1
方法名:sleep
	方法返回值类型:void
	方法修饰符:2
方法名:getAge
	方法返回值类型:int
	方法修饰符:1
方法名:setAge
	方法返回值类型:void
	参数名:int
	方法修饰符:1
方法名:eat
	方法返回值类型:void
	参数名:int
	方法修饰符:1
方法名:eat
	方法返回值类型:void
	方法修饰符:1
------ ------ ------
今天吃了1顿大餐
今天吃了3顿大餐
非常舒服的睡了一觉
*/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/416366.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于java SSM springboot动物检疫信息管理系统设计和实现

基于java SSM springboot动物检疫信息管理系统设计和实现 博主介绍&#xff1a;多年java开发经验&#xff0c;专注Java开发、定制、远程、文档编写指导等,csdn特邀作者、专注于Java技术领域 作者主页 央顺技术团队 Java毕设项目精品实战案例《500套》 欢迎点赞 收藏 ⭐留言 文末…

AI:145-智能监控系统下的行人安全预警与法律合规分析

🚀点击这里跳转到本专栏,可查阅专栏顶置最新的指南宝典~ 🎉🎊🎉 你的技术旅程将在这里启航! 从基础到实践,深入学习。无论你是初学者还是经验丰富的老手,对于本专栏案例和项目实践都有参考学习意义。 ✨✨✨ 每一个案例都附带关键代码,详细讲解供大家学习,希望…

milvus upsert流程源码分析

milvus版本:v2.3.2 整体架构: Upsert 的数据流向: 1.客户端sdk发出Upsert API请求。 import numpy as np from pymilvus import (connections,Collection, )num_entities, dim 4, 3print("start connecting to Milvus") connections.connect("default",…

代码随想录刷题训练营day25:LeetCode(216)组合总和III、LeetCode(17)电话号码的字母组合

代码随想录刷题训练营day25&#xff1a;LeetCode(40)组合总和 II、LeetCode(216)组合总和III、LeetCode(17)电话号码的字母组合 LeetCode(40)组合总和 II 题目 代码 import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util…

lv19 多态 4

1 虚函数 虚函数&#xff08; 基类指针可指向派生类对象&#xff0c; 动态联编&#xff09; 先看示例&#xff0c;不加virtual&#xff0c;不认对象认指针。 #include <iostream>using namespace std;class A{ public:A(){ }~A(){ }void show(){cout<<"AAA…

火灾安全护航:火灾监测报警摄像机助力建筑安全

火灾是建筑安全中最常见也最具破坏力的灾难之一&#xff0c;为了及时发现火灾、减少火灾造成的损失&#xff0c;火灾监测报警摄像机应运而生&#xff0c;成为建筑防火安全的重要技术装备。 火灾监测报警摄像机采用高清晰度摄像头和智能识别系统&#xff0c;能够全天候监测建筑内…

LeetCode #104 二叉树的最大深度

104. 二叉树的最大深度 题目 二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;3 示例 2&#xff1a; 输入&#xff1a;root [1,null,2] 输出&#xff1a;2 分析 …

程序员缺乏经验的 7 种表现!

程序员缺乏经验的 7 种表现&#xff01; 一次性提交大量代码 代码写的很烂 同时开展多项工作 性格傲慢 不能从之前的错误中学到经验 工作时间处理私人事务 盲目追逐技术潮流 知道这些表现&#xff0c;你才能在自己的程序员职业生涯中不犯相同的错误。 软件行业的工作经…

Zookeeper基础入门-2【ZooKeeper 分布式锁案例】

Zookeeper基础入门-2【ZooKeeper 分布式锁案例】 四、ZooKeeper-IDEA环境搭建4.1.环境搭建4.1.1.创建maven工程&#xff1a;zookeeper4.1.2.在pom文件添加依赖4.1.3.在项目的src/main/resources 目录下&#xff0c;新建文件为“log4j.properties”4.1.4.创建包名com.orange.zk …

springboot 注解属性转换字典

1.注解相关功能实现 定义属性注解 import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.vehicle.manager.core.serializer.DicSerializer;import java.lang.annotation.*;/*** a…

c++学习记录 deque容器—数据存取

函数原型&#xff1a; at(int idx); //返回索引idx所指的数据operator[]; //返回索引idx所指的数据front(); //返回容器中第一个数据元素back(); //返回容器中最后一个数据元素 #include<iostream> using nam…

websocket在django中的运用

14-2 聊天室实现思路&#xff1a;轮训、长轮训、websocket_哔哩哔哩_bilibili 参考大佬的B站学习笔记 https://www.cnblogs.com/wupeiqi/p/6558766.html 参考博客 https://www.cnblogs.com/wupeiqi/articles/9593858.html 参考博客 http协议: 是短连接&#xff0c;无状态…

【LeetCode】每日一题:使二叉树所有路径值相等的最小代价

该题采用自底向上的思路的话&#xff0c;很容易想到使用贪心的思想&#xff0c;但是如何进行具体操作却有些难度。 这里补充一个重要的结论&#xff1a;二叉树的数组形式中&#xff0c;第i个节点的父节点是i/2&#xff1b;接下来只需要让自底向上让每个路径上的代价保持最低限…

Python实现自动检测设备连通性并发送告警到企业微信

背景&#xff1a;门禁机器使用的WiFi连接&#xff0c;因为某些原因会不定期自动断开连接&#xff0c;需要人工及时干预&#xff0c;以免影响门禁数据同步&#xff0c;故写此脚本&#xff0c;定时检测门禁网络联通性。 #首次使用要安装tcping模块 pip install tcpingfrom tcpin…

Jupyter Notebook 下载+简单设置

这里写目录标题 1. Jupyter Notebook安装2.切换打开别的盘3. 创建代码文件4.为jupyter notebook添加目录 (Jupyter安装拓展nbextensions)step1&#xff1a;安装命令step2&#xff1a;用户配置step3&#xff1a;上述过程均完成后&#xff0c;打开jupyter notebook就会发现界面多…

静态方式部署集中式网关

在静态方式部署集中式网关的场景中&#xff0c;控制平面的流程包括VXLAN隧道建立、MAC地址动态学习&#xff1b;转发平面的流程包括同子网已知单播报文转发、同子网BUM&#xff08;Broadcast&Unknown-unicast&Multicast&#xff09;报文转发、跨子网报文转发。 静态方…

qml 项目依赖

文章目录 出现的问题最终对比下一步 把 apptestQml3_6.exe 放到一个单独目录下&#xff0c;执行 windeployqt.exe ./apptestQml3_6.exe但是出了很多问题&#xff0c;根本运行不起来。 但是在release目录下执行下&#xff0c;程序能跑起来。 根据错误提示&#xff0c;进行添加。…

vue3+vite+ts配置多个代理并解决报404问题

之前配置接口代理总是报404,明明接口地址是对的但还是报是因数写法不对;用了vue2中的写法 pathRewrite改为rewrite 根路径下创建env文件根据自己需要名命 .env.development文件内容 # just a flag ENVdevelopment# static前缀 VITE_APP_PUBLIC_PREFIX"" # 基础模块…

php 支持mssqlserver

系统不支持:sqlsrv 需要一下几个环节 1.准备检测php版本 查看 VC 版本 查看操作系统位数&#xff1a;X86(32位) 和X64 2.下载php的sqlserver库 extensionphp_sqlsrv_74_nts_x64.dll extensionphp_pdo_sqlsrv_74_nts_x64.dll extensionphp_sqlsrv_74_nts_x64 extensionphp_…

基于Vue的高校课程考勤成绩管理系统SpringBoot+nodejs+python

设计目标&#xff1a; 课程管理系统开发的目的是管理全校开设课程的基本信息&#xff0c;安排各班级的课程以及上课时间和教室。系统的使用对象包括教务,学生、教师、管理员等。通过对日常课程管理工作的分析&#xff0c;可以将课程管理系统的功能分为下面几个方面&#xff1a…