最近和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());
}
}
功能简单,但是学习到了一些新知识还是很开森的。