Java面向对象知识点总结05---反射 invoke

反射

关于反射是啥东西

反射,简单来说可以把一个Java类中的所有组成部分(成员变量,构造函数,成员方法,子类等)分别提取出来(分别有对应的类),并对组成成分进行操作。

组成部分对应的类
Package
类,接口,父类Class
成员变量Field
构造函数Constructor
成员方法Method
关于反射有啥用

平常自己能用到的有:破坏修饰符(访问private方法),在程序运行时创建实例,查看类的信息,这三个用处。
反射在框架的开发中有十分强大的作用。

关于反射怎么用
package test;
import java.io.*;
//这里有一个Students类
public class Student implements Serializable {
    int num;
    String name;
    private int count;//私有成员变量

    private Student() {//私有构造方法
    }

    public Student(int num, String name, int count) {
        this.num = num;
        this.name = name;
        this.count = count;
    }

    private void announceName() {//私有成员方法
        System.out.println(name);
    }
}

我们若要获得一个类的对象,注意不是类的实例,我们这个对象是个类,使用该方法

Class<?> clazz = Class.forName("类的路径(包名.类名)");

我们若要获得一个类的构造器,在上面类的对象的方法中调用该方法
由于构造函数的多态性,我们需要通过传入参数的形式来指定我们需要的构造器
比如在上面的Students类中public Student(int num, String name, int count)这个构造函数是含参的,请注意在下面获得构造器的过程中传入对应的参数

Constructor<?> constructor = clazz.getConstructor();
//获得默认构造器的方法
Constructor<?> constructor = clazz.getDeclaredConstructor(int.class, String.class, int.class);
//获得由用户声明的构造器的方法

当我们获得了构造器,我们就可以构造出实例了

Constructor<?> constructor = clazz.getDeclaredConstructor(int.class, String.class, int.class);
//这里是获得由用户声明构造器
constructor.setAccessible(true);
//由于这里的构造器是私有的我们需要这个方法来强制获得可访问性
//若是公共的构造器则不需要此方法
Student student = (Student) constructor.newInstance(123,"abc",456);
//使用构造器类的newInstance方法,并传入对应的参数

我们可以通过如下方法获得成员变量

Field field = clazz.getDeclaredField("count");//获得由用户声明的变量
field.setAccessible(true);//同样强制获得可访问性,若是公共的则不需要此方法
field.set(student, 123);
//可以通过Field类的set方法来进行成员变量的设置
//第一个参数为要被设置成员变量的实例
//第二个参数为成员变量要被设置的值

当我们想要获得全部方法信息的时候可以这么做

Method[] allMethods = clazz.getMethods();//获得全部的方法
for ( var i : allMethods ) {
    System.out.println(i);
}

System.out.println();

Method[] declaredMethods = clazz.getDeclaredMethods();//获得由用户声明的方法
for ( var i : declaredMethods ) {
    System.out.println(i);
}

输出为:可以看到,全部的方法中包含继承而来的方法

public int assignment.Student.a()
public boolean java.lang.Object.equals(java.lang.Object)
public java.lang.String java.lang.Object.toString()
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
public final void java.lang.Object.wait(long) throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final void java.lang.Object.wait() throws java.lang.InterruptedException

private void assignment.Student.announceName()
public int assignment.Student.a()

当我们知道所有的信息了之后我们就可以通过名称调用对应的方法了
当我们需要调用类的方法时我们可以这么做

Method method = clazz.getDeclaredMethod("announceName");
//通过传入方法名的方式获得由用户声明的方法对象
method.setAccessible(true);//同样强制获得可访问性,若是公共的则不需要此方法
method.invoke(student);
//通过Method类的invoke方法来指定实例调用该方法,若是静态方法第一个参数为null
//若是含参的方法须在第二个参数(不定长参数)的位置传入形参
//注意这里的invoke和使用Lambda表达式实现接口时的invoke没有关系

关于不定长参数请看这里

全部测试代码如下

package test;
import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Test {
    public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
        Class<?> clazz = Class.forName("test.Student");
        
        Constructor<?> constructor = clazz.getDeclaredConstructor(int.class, String.class, int.class);
        constructor.setAccessible(true);
        
        Student student = (Student) constructor.newInstance(123,"abc",456);

        Field field = clazz.getDeclaredField("count");
        field.setAccessible(true);
        field.set(student, 789);
        
        Method method = clazz.getDeclaredMethod("announceName");
        method.setAccessible(true);
        method.invoke(student);//输出abc
        
        System.out.println(field.get(student));//输出789
    }
}

参考文献

CSDN: Java的反射机制到底是什么?有什么用?
CSDN: 什么是java反射机制?反射的作用和意义!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LXTTTTTTTT

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值