Java 利用反射类操作其他类

本文深入浅出地介绍了Java反射机制的基本概念及应用。通过实例演示如何利用反射获取类的属性和方法,并展示了如何操作私有成员。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

反射的概念:
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象.

反射就是把java类中的各种成分映射成一个个的Java对象
例如:一个类有:成员变量、方法、构造方法、包等等信息,利用反射技术可以对一个类进行解剖,把个个组成部分映射成一个个对象。(其实:一个类中这些成员方法、构造方法、在加入类中都有一个类来描述)

Class反射类一直是Java中较为重要的一部分,说深入了解不敢说,基础的操作其他类的公有属性/方法,私有的属性/方法做个操作,什么是反射类,请参考其他更为详细的文章。

首先创建一个类,Student类:

public class Student {
    private String name;
    private String sex;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void run(){
        System.out.println("奔跑");
    }

    private String say(String str){
        return "他说"+str;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", sex='" + sex + '\'' +
                ", age=" + age +
                '}';
    }
}
在这个类中,有三个私有的属性,一个无返回值无参的方法,一个有返回值有参的方法,现在要利用Class反射类要做一个操作,获取这个Student类中的属性并赋值,调用这个类的方法

介绍一下获取Class对象的三种方式:

1、 Object ——> getClass();(封装时常用)
2、 任何数据类型(包括基本数据类型)都有一个“静态”的class属性
3、 通过Class类的静态方法:forName(String  className)(常用)

第一种:

Student student = new Student();//这一new 产生一个Student对象,一个Class对象。  
Class cls = student.getClass();//获取Class对象  
第二种:

Class sls = Student.class;
第三种:

Class sls = Class.forName("com.uhope.uip.item.constants.Student");
第三种就是类所在包的完整路径

三种写法,看自己的需求来写,我这里要介绍的是第一种,因为我对这个反射类进行了一次的封装,封装成工具类方便调用。

创建好了Student类以后,创建一个测试类来进行测试一下看看效果:

在不知道类名的情况下,不把代码写死,想要写的灵活点,那就让使用这个工具类的人自己传一个类进来,那方法中的参数就放一个Object,Object是所有类的父类,所以都是没问题的:

public static void ClassUtil(Object obj){
    Class cls = obj.getClass();
}
这样就获取到了别人传入的类

接着要操作类的方法,使用Method:

public static void ClassUtil(Object obj){
    try {
        Class cls = obj.getClass();
        Method method = cls.getMethod("setName",String.class);
        method.invoke(obj,"测试名称");
        System.out.println(obj);
    } catch (NoSuchMethodException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    }

}
这是操作公有方法的写法,接下来是操作私有方法的写法:

public static void ClassUtil(Object obj){
    try {
        Class cls = obj.getClass();
        Method method = cls.getDeclaredMethod("say",String.class);
        method.setAccessible(true);
        method.invoke(obj, "哈喽");
    } catch (NoSuchMethodException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    }
}
say是private封装的方法,setName是公有方法,操作私有的,需要 setAccessible(true) 来解除私有状态,还有一个不一样的是需要getDeclaredMethod而不是getMethod方法了,getDeclaredMethod是为了私有方法准备的,由于say是有返回值的方法,这里就不需要System.out.println了,在打印中就会展示出来


接下来是操作Student类中的run方法,run是一个无返回值无参的方法,但是里面写好了内容,这样的话只需要如下代码:

public static void ClassUtil(Object obj){
    try {
        Class cls = obj.getClass();
        Method method = cls.getMethod("run");
        method.invoke(obj);
    } catch (NoSuchMethodException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    }
}
三种操作方法的演示好了,需要注意的就是getDeclaredMethod和getMethod方法的使用区别,以及有无参数的区别,有参数的话要多写两个地方,一个是Method的第二个参数类型,一个是invoke的第二个指定的值。

接下来看调用私有的属性(一般项目中都是私有封装的,所以就讲解一下私有操作),调用方法是Method,调用属性是用Field:

public static void ClassUtil(Object obj){
    try {
        Class cls = obj.getClass();
        Field field = cls.getDeclaredField("name");
        field.setAccessible(true);
        field.set(obj,"测试名称");
        System.out.println(field.get(obj));
    }catch (IllegalAccessException e) {
        e.printStackTrace();
    }catch (NoSuchFieldException e) {
        e.printStackTrace();
    }
}
和获取私有方法相同,都有一个getDeclared,也需要解除私有状态,通过Field中的set方法,将要给与的值赋进去,查看有没有赋值成功,就用Field的get方法即可,也可以通过Method获取setName方法,将参数写进去,再用Field获取值:

public static void ClassUtil(Object obj){
    try {
        Class cls = obj.getClass();
        Method method = cls.getMethod("setName",String.class);
        method.invoke(obj,"Method测试名称");
        Field field = cls.getDeclaredField("name");
        field.setAccessible(true);
        System.out.println(field.get(obj));
    }  catch (NoSuchFieldException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (NoSuchMethodException e) {
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值