JAVA基础(12)——反射

这篇博客详细介绍了JAVA中的反射机制,包括通过Class获取数据结构,实例化对象,调用对象方法,并通过实际例子展示了如何使用反射进行对象复制。还简述了反射在动态代理中的应用。

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

JAVA基础系列规划:


个人把java反射理解为一种框架,在框架内可以通过名称来控制类结构及其对象。而框架的基础就是java.lang.Class类和java.lang.reflect包中的Field、Constructor、Method、Array类。

Class类的实例表示正在运行的Java应用程序中的类和接口,保存它们的运行时类型标识信息。因此,它是java反射的开始,只有获得Class类的对象,才能通过这个对象获取其他相关信息。

获取一个类对象的Class,有三种方式:

Class classInstance = Person.class; //类型名.class获取该类型对应的Class对象
Class classInstance = Class.forName("Person"); //Class类的forName()静态方法获得与字符串对应的Class对象
Class classInstance = new Person().getClass(); //调用Object类对象的getClass()方法类得到Class对象

1. 获取数据结构

从Class开始,可以获取classInstance所关联的类的类名:

classInstance.getName(); //获得类的完整名字

不仅如此,类里面的所有东西都可以获取,Field、Constructor、Method,分别对应着类的成员变量、构造方法和成员方法。

Field[] fields = classInstance.getFields(); //获得类的public类型的属性

这样就获取了类的属性,但注意,只是public类型的属性,要获取类的所有属性,需要

Field[] fields = classInstance.getDeclaredFields(); //获得类的所有属性

要通过属性名称来获取类属性,就需要下面的方法了:

Field field = classInstance.getField("profession"); //public类型属性适用
Field field = classInstance.getDeclaredFields("profession"); //所有类型属性均适用

获取构造方法类似:

Constructor[] cs = classInstance.getConstructors(); //获得类的public类型的构造方法
Constructor[] cs2 = classInstance.getDeclaredConstructors(); //获得类的所有构造方法

Class parameterTypes[] = { java.lang.String.class }; //parameterTypes参数指定构造方法的参数类型
Constructor c = classInstance.getConstructor(parameterTypes); //public类型构造方法适用
Constructor c2 = classInstance.getDeclaredConstructor(parameterTypes);//所有类型构造方法适用

Constructor c3 = classInstance.getEnclosingConstructor(); //获取本地或匿名类Constructor对象

获取成员方法类似:

Method[] ms = classInstance.getMethods();//获得类的public类型的方法
Method[] ms2 = classInstance.getDeclaredMethods();//获得类的所有方法

String methodName = "setName";
Class methodParaTypes[] = { java.lang.String.class }; //methodParaTypes参数指定方法的参数类型
Method m2 = classInstance.getMethod(methodName, methodParaTypes);//public类型构造方法适用
Method m3 = classInstance.getDeclaredMethod(methodName, methodParaTypes);//所有类型构造方法适用

2. 实例化对象

不仅可以获取类的内部结构,还可以实例化出对象,方法为:

Person p = (Person)classInstance.getConstructor(new Class[] {}).newInstance(new Object[] {}); //通过类的不带参数的构造方法创建类对象

上句是通过类的不带参数的构造方法创建类对象,还可以用另一种表达:

Person p2 = (Person)classInstance.newInstance(); //通过类的不带参数的构造方法创建类对象

对于带参数的构造方法,就只有一条路了:

Person p3 = (Person)classInstance.getConstructor(new Class[] {java.lang.String.class}).newInstance(new String[] {"best"}); //通过类的带参数的构造方法创建类对象。

3. 调用实例化对象方法

使用Method,传递参数,隐式调用执行对象的方法:

String methodName2 = "getName";
Method m4 = classInstance.getMethod(methodName2);
Object value = m4.invoke(new Person(), new Object[] {});

4. 举个栗子

仿commons-beanutils中复制对象,这是一个运行时复制对象的过程。

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

public class BeanHelper {

    public static Object copy(Object object) throws Exception {
        Class classInfo = object.getClass();

        Object objectCopy = classInfo.newInstance();

        Field fields[] = classInfo.getDeclaredFields();

        for(int i=0; i<fields.length; i++) {
            Field field = fields[i];

            String fieldName = field.getName();
            String firstLetter = fieldName.substring(0, 1).toUpperCase();
            String getMethodName = "get" + firstLetter + fieldName.substring(1);
            String setMethodName = "set" + firstLetter + fieldName.substring(1);

            Method getMethod = classInfo.getMethod(getMethodName, new Class[] {});
            Method setMethod = classInfo.getMethod(setMethodName, new Class[] { field.getType() });

            Object value = getMethod.invoke(object, new Object[] {});
            setMethod.invoke(objectCopy, new Object[] { value });
        }

        return objectCopy;

    }

}

小测一下:

public class Main {

    public static void main(String[] args) throws Exception {
        Person p = new Person();
        Person p2 = (Person)BeanHelper.copy(p);
        System.out.println(p2.getName());
    }

}

5. 反射与动态代理

在企业应用高级框架中大量用到代理模式,其原理主要就是应用到反射。

详见代理http://www.blogjava.net/baoyaer/articles/84080.html

6. 附

public class Person {
    private String name;
    private String sex;
    private String age;

    public Person() {
        name = "default";
        sex = "male";
        age = "25";
    }

    public Person(String name) {
        this.name = name;
        sex = "male";
        age = "25";
    }

    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 String getAge() {
        return age;
    }
    public void setAge(String age) {
        this.age = age;
    }

    public void walk(float length) {
        System.out.println("walk " + length);
    }

}

7. 参考文档

Java反射机制深入研究 JAVA的内省(introspector)与反射(reflection)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值