用反射实现对象的拷贝 及 利用内省类实现对象的复制

本文介绍两种Java对象深拷贝的方法:一种是利用反射直接操作字段,另一种是使用java.beans.Introspector类进行拷贝。这两种方法均适用于遵循JavaBean规范的对象。

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

package com.java1029.reflect;

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

public class CopyObject {


	/**
	 * 对象的拷贝(对象必须遵循JavaBean规范)
	 * 
	 * 1.获取所有的Field对象
	 * 2.遍历所有的Field对象
	 * 3.获取对应Field对象的setXX()/getXX()方法的Name
	 * 4.通过3步获取的方法的Name,获取被复制对象t对应属性Field的getXX()/setXX()方法的Method对象
	 * (注:4步中获取setXX()对应的Method对象需要参数类型,该类型可以通过geXX()方法对应的Method获取)
	 * 5.获取getXX方法返回值para:执行getXX()方法对应的Method对象的invoke(t)方法。参数应该为t和null,null课省略
	 * 6.为新建的对象o执行setXX()方法:用setXX()对象对应的Method对象,执行invoke(o,para)方法。参数应该为新建对象o和5中获取的返回值para
	 * @param t
	 * @return
	 * @throws Exception
	 */
	public static <T> T copy(T t) throws Exception {
		// 获得对象参数类型T的运行期间对象
		Class<?> clz = t.getClass();
		Field[] fields = clz.getDeclaredFields();
		Object o = clz.newInstance();
		for (Field f : fields) {
			String fieldName = f.getName();
			//首字母大写
			String firstLetter = fieldName.substring(0, 1).toUpperCase();
			// get方法的方法名
			String getMethodName = "get" + firstLetter + fieldName.substring(1);
			// set方法的方法名
			String setMethodName = "set" + firstLetter + fieldName.substring(1);
			Method getMethod = clz.getMethod(getMethodName);
			// 该属性对应的set方法的返回值类型的Class对象
			Class<?> getMethodReturnType = getMethod.getReturnType();
			
			//Method setMethod = clz.getMethod(setMethodName, new Class<?>[]{f.getType()});
			//以上代码可以替换下行代码(上行代码是利用该对应Field对象的类型设置setXxx()方法的参数类型)
			Method setMethod = clz.getMethod(setMethodName, getMethodReturnType);
			// 通过get方法获取t对象的对应该属性的值,来作为o对象set方法的参数
			Object para = getMethod.invoke(t);
			//为o对象调用该属性对应的set方法
			setMethod.invoke(o, para);
		}

		return (T) o;// 应该返回新的对象
	}

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

		Student s = new Student();
        s.setAge(5);
		s.setName("c10");

		Student o = CopyObject.copy(s);
        System.out.println("o.getName()->"+o.getName());
        System.out.println("o.getAge()->"+o.getAge());
         
	}

}

/**
 * 学生类
 * @author ml1990s
 *
 *//*
class Student {
	  private String name;
	  private int 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;
	}
	}

*/



以下为使用内省类java.beans.Introspector  实现对象复制

package com.java1029.reflect.emphasis;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;

public class CopyObjectUseBeans {

    /**
     * 对象的拷贝(对象必须遵循JavaBean规范)
     * 
     * @param t
     * @return
     * @throws Exception
     */
    public static <T> T copy(T t) throws Exception {
        // 获得对象参数类型T的运行期间对象
        Class<?> clz = t.getClass();
        T o = (T) clz.newInstance();
        //通过Introspector内省类 获取BeanInfo 描述T的Bean类信息类
        BeanInfo beanInfo = Introspector.getBeanInfo(clz);
        //
        PropertyDescriptor[] descs = beanInfo.getPropertyDescriptors();
       
        for(int i=0,length = descs.length;i<length;i++){
            PropertyDescriptor desc = descs[i];
            if(!desc.getName().equals("class")){
            Method getMethod = desc.getReadMethod();
            Method setMethod = desc.getWriteMethod();
            System.out.println(setMethod);
            
            Object property = getMethod.invoke(t);
            setMethod.invoke(o, property);
            }
        }
        return o;// 应该返回新的对象
    }

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

        Student s = new Student();
        s.setAge(5);
        s.setName("c10");

        Student o = CopyObjectUseBeans.copy(s);
        System.out.println("o.getName()->" + o.getName());
        System.out.println("o.getAge()->" + o.getAge());

    }

}

/**
 * 学生类
 * 
 * @author ml1990s
 * 
 */
/*
 * class Student { private String name; private int 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; } }
 */


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值