Java的反射简介

广告也精彩

前言

本文主要参考其他作者的文章,然后自己整理一下,原文写得很仔细,但还得自己走一遍流程。

感谢大佬分享。

正文

什么是Java的反射机制

java允许开发者在程序运行过程中操作(访问和修改)类的各种属性以及方法。

获取Class类对象

java给我们提供了三种方式获取Class类对象。

Source(源代码阶段)
Class clz = Class.forName("com.biumall.demo.Person");

这个方法就是通过Java文件的全限定名(包名+类名)把它的class文件加载到JVM内存里面,此时我们就能得到Class类文件,由于是源代码阶段。

Class类对象
Class clz = Person.class;

这个就直接用的Person的静态属性

Runtime(运行时)

因为是运行时了,首先我们得先有Person这个对象

Pserson p = new Person();
Class clz = p.getClass();

Class类对象能干什么?

Class类对象是对类的描述,拿到了所有类的信息,理论上我们就什么都能干,比如说:获取类的构造方法、成员变量、成员方法、类名等等。

下面分别对获取类的构造方法、变量和方法进行简单介绍。

定义一个Person类进行测试

public class Person {

    private String mName;
    private int mAge;
    private int mID;
    private int mSex;

    public Person() {

    }

    private Person(int id) {
        mID = id;
    }

    public Person(String name, int age) {
        mName = name;
        mAge = age;
    }

    protected Person(int id, int sex) {
        mID = id;
        mSex = sex;
    }

    public String getName() {
        return mName;
    }

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

    public int getAge() {
        return mAge;
    }

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

    public int getID() {
        return mID;
    }

    public void setID(int mID) {
        this.mID = mID;
    }

    public int getSex() {
        return mSex;
    }

    public void setSex(int mSex) {
        this.mSex = mSex;
    }

    @Override
    public String toString() {
        return "Person{" +
                "mName='" + mName + '\'' +
                ", mAge=" + mAge +
                ", mID=" + mID +
                ", mSex=" + mSex +
                '}';
    }
}

PS: 提前说明一下。下面写法不一样,但效果一样。

//写法不同,效果一样
Class clz = Person.class;
Class<Person> clz = Person.class;

或者

//写法不同,效果一样
Constructor[] constructors= clz.getConstructors();
Constructor<Person>[] constructors= clz.getConstructors();
Constructor<?>[] constructors = clz.getDeclaredConstructors();

言归正传,下面进入话题。

获取Person类对象

Class<Person> clazz = Person.class;
类的构造方法
获取Public的所有构造函数

只有public的构造函数才能获取。

Constructor<?>[] constructors = clazz.getConstructors();

获取的是数组,可以遍历一下。输出的结果:

public com.biumall.demo.Person()
public com.biumall.demo.Person(java.lang.String,int)
获取所有的构造函数

可以把类中所有的构造函数获取

Constructor<?>[] constructors = clazz.getDeclaredConstructors();

输出的结果:

public com.biumall.demo.Person()
private com.biumall.demo.Person(int)
protected com.biumall.demo.Person(int,int)
public com.biumall.demo.Person(java.lang.String,int)
获取指定参数类型的构造函数
Constructor<?> constructor = clazz.getConstructor(String.class, int.class);

输出结果:

public com.biumall.demo.Person(java.lang.String,int)
创建对象

上面几种方式都可以获取了类的构造方法对象Constructor,既然获取了那肯定得用用,也就是可以创建对象。

Constructor中提供了一个创建对象的方法:

public T newInstance(Object ... initargs)

具体如何使用,请继续。

我们获取指定类对象的构造函数

private Person(int id)

这个构造函数。

Constructor<?> constructors = clazz.getDeclaredConstructor(int.class)
//如何使用获取的构造函数
constructor.setAccessible(true);
//创建Person对象[private Person(int id) ]
Person person = (Person) constructors.newInstance(1);
//获取初始化的ID
person.getID();

PS: constructor.setAccessible(true);,当我们访问private修饰的构造方法、成员变量、成员方法,都需要调用这个API,它的意思是取消安全检查机制。

类的变量
//获取所有变量
Field[] fields = clazz.getFields();
//获取指定变量名的的public变量(只能获取到public
Field fieldName = clazz.getField("mName");
//获取指定变量名,不受修饰符影响(publicprivateprotected
Field fieldName = clazz.getDeclaredField("mName");
改变变量值

既然获取了类的变量,那肯定得操作一番的。

Constructor<Person> constructor = clazz.getConstructor(String.class, int.class);
constructor.setAccessible(true); //必须配置
//创建对象
Person person = constructor.newInstance("biumall.com", 20);

//获取指定变量名的变量
Field fieldName = clazz.getDeclaredField("mName");
//上面说了,这个方法必须调用如果操作私有
fieldName.setAccessible(true);
//获取变量mName的值
String name = (String) fieldName.get(person);
//重新改名
fieldName.set(person, "125la.com");
////获取变量mName修改过后的值
String name2 = (String) fieldName.get(person);
类的方法

跟上面一样,也可以获取类方法

//获取所有方法
Method[] methods1 = clazz.getDeclaredMethods();
//获取所有的public方法
Method[] methods2 = clazz.getMethods();
//获取指定参数的方法
Method method1 = clazz.getMethod("setName", String.class);
Method method2 = clazz.getDeclaredMethod("setName", String.class);
通过方法改变变量值

Constructor<Person> constructor = clazz.getConstructor(String.class, int.class);
constructor.setAccessible(true); //必须配置
//创建对象
Person person = constructor.newInstance("biumall.com", 20);

Method method = clazz.getMethod("setName", String.class);
method.setAccessible(true);
//person通过调用setName改变name
method.invoke(person, "www.125la.com");

参考文章

  1. 夯实基础:Java的反射

广告也精彩
版权声明:125la.com站长 发表于 2022年6月23日 上午8:08。
转载请注明:Java的反射简介 | 125啦读书导航

相关文章

广告也精彩

暂无评论

暂无评论...