首页 > 代码库 > 使用Java对两个对象的属性进行拷贝

使用Java对两个对象的属性进行拷贝

最近和Java的反射打交道比较多一点,可能是因为自己以后的方向是架构师的缘故吧,他们主要搞业务。我能也就搞架构,整天画一些流程图。

虽然对于只有一年实习经验的我,不知道这样是否好,但是我还是那句话,不论好坏,先走着,毕竟也能学到很多东西,而且还可以锻炼自己的思维能力。

表达能力,因为自己的产品做的再好,你就是表达不出来,说不出来优势,那么你就败了。

先创建一个实体类User

package com.mine.practice.copyproperty.entity;
/**
  *
  * @author 2014-11-6 上午10:28:10 
  * @version V1.0  
 */
public class User {

	private int id;
	
	private String name;
	
	private String pwd;

	private double idG;
	
	public double getIdG() {
		return idG;
	}

	public void setIdG(double idG) {
		this.idG = idG;
	}

	public String getPwd() {
		return pwd;
	}

	public void setPwd(String pwd) {
		this.pwd = pwd;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

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

}


然后就是具体的拷贝已经测试代码了。

package com.mine.practice.copyproperty.test;
import java.lang.reflect.Field;
import com.mine.practice.copyproperty.entity.User;
/**
  * 属性拷贝
  * @author 2014-11-6 上午10:29:32 
 */
public class TestCopyProperty {

	/**
	 *  业务需求:
	 *  	对于某些业务进行某个或某些类的数据更新时,只想更新该类的部分字段,其它字段还使用之前的值。
	 * 
	 *  遇到问题:
	 *  	当有些业务需要增加或减少某个类的字段个数、修改字段名称时,前台可能只需要修改一个地方就可以解决了。
	 *  但是后台由于采用的事件的方式进行处理,所以会有多个地方使用,修改起来比较困难。   
	 *  
	 *  主要解决问题:
	 *     即使字段个数或者字段名称修改后后台代码也不需要修改。  
	 *       
	 *  解决方案:
	 *      在借鉴之前的解决方案的基础上进行了修改。
	 *      通过遍历该类的所有属性,然后获取新类的属性值,如果新类的属性值不为null、空字符串、基本类型的默认值
	 *      则把新的对象的属性值赋值给老的对象属性
	 * 
	 *  优点:1、即使增加或者修改字段个数后台也不需要改动
	 *      2、即使修改字段名称或者类型后台也不需要改动 
	 *  
	 *  缺点:1、会遍历一个类的所有属性,并且判断新对象的属性值:是否存在以及是否为默认值。批量数据时性能会有些差
	 *      2、由于基本数据类型会有默认值,所以框架不知道这个字段的值到底要不要修改到新的对象上面。
	 *       
	 *  
	  * @author 2014-11-6 上午11:01:03
	  * @param args
	  * @throws SecurityException
	  * @throws NoSuchFieldException
	  * @throws IllegalArgumentException
	  * @throws IllegalAccessException 
	  * @modificationHistory=========================逻辑或功能性重大变更记录 
	  * @modify by user: {修改人} 2014-11-6
	  * @modify by reason:{原因}
	 */
	public static void main(String[] args) throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
		
		//老对象
		User oldUser = new User();
		oldUser.setId(1);
		oldUser.setName("name1");
		oldUser.setPwd("pwd1");
		oldUser.setIdG(1.2);
		
		System.out.println("数据库中的老对象");
		print(oldUser);
		
		//新对象
		User newUser = new User();
		newUser.setName("name2");
		
		System.out.println("前台传递过来的新对象");
		print(newUser);
		
		//功能需求
		//把之前的老对象的id和name修改掉,但是pwd不需要修改
		copyProperty(oldUser,newUser);
		
		System.out.println("----------老对象被修改后-------------");
		print(oldUser);
	}
	
	/**
	 * 
	  * @author 2014-11-6 上午11:26:36
	  * @param oldUser
	  * @param newUser 
	 * @throws NoSuchFieldException 
	 * @throws SecurityException 
	 * @throws IllegalAccessException 
	 * @throws IllegalArgumentException 
	  * @modificationHistory=========================逻辑或功能性重大变更记录 
	  * @modify by user: {修改人} 2014-11-6
	  * @modify by reason:{原因}
	 */
	@SuppressWarnings("rawtypes")
	private static void copyProperty(User oldUser,User newUser) throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException{
		//新的class
		Class newClass = newUser.getClass();
		//老的class
		Class oldClass = oldUser.getClass();
		//该类所有的属性
		Field[] newFields = newClass.getDeclaredFields();
		//新的属性
		Field newField = null;
		//老的属性
		Field oldField = null;
		for(Field f : newFields){
			//类中的属性名称
			String fieldName = f.getName();
			//通过属性名称获取属性
			newField = newClass.getDeclaredField(fieldName);
			//获取属性的值时需要设置为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查。
			//值为 false 则指示反射的对象应该实施 Java 语言访问检查。 
			newField.setAccessible(true);
			//根据属性获取对象上的值
			Object newObject = newField.get(newUser);
			//过滤空的属性或者一些默认值
			if (isContinue(newObject)) {
				continue;
			}
			oldField = oldClass.getDeclaredField(fieldName);
			oldField.setAccessible(true);
			oldField.set(oldUser, newObject);
		}
	}
	
	/**
	 *  是否跳出本次循环
	  * @author 2014-11-6 上午11:37:22
	  * @param object
	  * @return true 是 有null或者默认值
	  *         false 否 有默认值
	 */
	private static boolean isContinue(Object object){
		if (object == null || "".equals(object)) {
			return true;
		}
		String valueStr = object.toString();
		if ("0".equals(valueStr) || "0.0".equals(valueStr)) {
			return true;
		}
		return false;
	}
	
	/**
	  *  
	  * @author 2014-11-6 上午10:57:32
	  * @param user 
	 */
	private static void print(User user){
		System.out.println("id: "+user.getId());
		System.out.println("name: "+user.getName());
		System.out.println("pwd: "+user.getPwd());
		System.out.println("idG: "+user.getIdG());
	}
}

功能简单,但是学习到了一些新知识还是很开森的。

使用Java对两个对象的属性进行拷贝