POJO属性对拷(支持嵌套和继承)
来源:互联网 发布:思想深度 知乎 编辑:程序博客网 时间:2024/06/03 20:22
网上不少支持属性值对拷的工具,但是很多不支持嵌套对拷,比如apche的bean工具,这里自己造了个轮子,代码只实现了最粗糙的功能,如果网友要使用则需要稍微加工下,现在支持复合类型、数组类型、List类型,至于其他的Map类型等,网友可以自己扩展,参考已有的思路,很简单。
这里主要使用了反射的机制。
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
/**
* 对象属性值对拷
* <p>
* 两个bean中,具备以下条件的POJO之间可以进行属性对拷
* <li>field名称一样,且必须有get/set方法
* <li>如果field是简单类型,则field之间的类型必须一致
* <li>如果field是复合类型,则复合类型中的成员变量需要遵循上边的两个条件
* </p>
* @author zhaic
* @since jdk1.6
* 2015年10月26日
*
*/
public class BeanUtil {
/**
* 复制对象属性
* @param from
* @param to
*/
public static void copyProperties(Object from, Object to) {
// 如果对拷对象是简单类型,则直接忽略
if(isSimpleObject(from) || isSimpleObject(to)) {
return;
} else {
Field[] fields = getAllField(from.getClass());
for(Field tempField : fields) {
// 不关心final类型的字段
if(!Modifier.isFinal(tempField.getModifiers())) {
PropertyDescriptor fromPd = null;
try {
fromPd = new PropertyDescriptor(tempField.getName(), from.getClass());
Method getMethod = fromPd.getReadMethod();
Object value = getMethod.invoke(from, null);
if(null != value) {
if(isSimpleObject(value)) {// 简单对象处理
PropertyDescriptor toPd = new PropertyDescriptor(tempField.getName(), to.getClass());
Method setMethod = toPd.getWriteMethod();
setMethod.invoke(to, value);
} else if(value.getClass().isArray()) {// 数组类型处理
arrayCopy(tempField, value, to);
} else if(value instanceof java.util.List) {
listCopy(tempField, value, to);
} else {// 复杂类型则需要继续递归
complexCopy(tempField, value, to);
}
}
} catch (IntrospectionException e) {
continue;
} catch (IllegalAccessException e1) {
e1.printStackTrace();
} catch (IllegalArgumentException e1) {
e1.printStackTrace();
} catch (InvocationTargetException e1) {
e1.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
}
}
}
/**
* 判断是否简单对象
* @param o
* @return
*/
private static boolean isSimpleObject(Object o) {
Class<?> type = o.getClass();
if (type.isPrimitive()) { // 基本类型
return true;
}
// 不可更改的变量类型 如 String,Long
if (type.equals(String.class))
return true;
if (type.equals(Long.class))
return true;
if(type.equals(Boolean.class))
return true;
if(type.equals(Short.class))
return true;
if(type.equals(Integer.class))
return true;
if(type.equals(Character.class))
return true;
if(type.equals(Float.class))
return true;
if(type.equals(Double.class))
return true;
if(type.equals(Byte.class))
return true;
return false;}
/**
* 数组对象拷贝
* @param tempField
* @param from
* @param to
* @throws NoSuchFieldException
* @throws SecurityException
* @throws InstantiationException
* @throws IllegalAccessException
* @throws IntrospectionException
* @throws IllegalArgumentException
* @throws InvocationTargetException
*/
private static void arrayCopy(Field tempField, Object from, Object to)
throws NoSuchFieldException, SecurityException, InstantiationException,
IllegalAccessException, IntrospectionException,
IllegalArgumentException, InvocationTargetException {
int len = Array.getLength(from);
// 创建目标对象的成员变量
Field toField = to.getClass().getDeclaredField(tempField.getName());
Object array = Array.newInstance(toField.getType().getComponentType(), len);
for(int i = 0; i < len; i++){
Object toItemObj = toField.getType().getComponentType().newInstance();
Object fromItemObj = Array.get(from, i);
if(fromItemObj != null) {
if(isSimpleObject(fromItemObj)) {
toItemObj = fromItemObj;
} else {
copyProperties(fromItemObj, toItemObj);
}
Array.set(array, i, toItemObj);
}
}
PropertyDescriptor toPd = new PropertyDescriptor(tempField.getName(), to.getClass());
Method setMethod = toPd.getWriteMethod();
setMethod.invoke(to, array);
}
/**
*
* 完成列表成员变量的拷贝
* @param tempField
* @param from
* @param to
* @throws NoSuchFieldException
* @throws SecurityException
* @throws InstantiationException
* @throws IllegalAccessException
* @throws IntrospectionException
* @throws IllegalArgumentException
* @throws InvocationTargetException
*/
private static void listCopy(Field tempField, Object from, Object to)
throws NoSuchFieldException, SecurityException, InstantiationException,
IllegalAccessException, IntrospectionException,
IllegalArgumentException, InvocationTargetException {
// 创建目标对象的成员变量
Field toField = to.getClass().getDeclaredField(tempField.getName());
List toList = null;
// 根据具体的列表类型来判断
if(from instanceof ArrayList) {
toList = new ArrayList();
} else if(from instanceof LinkedList) {
toList = new LinkedList();
}
List<?> fromList = (List)from;
for(Object tempItem : fromList){
ParameterizedType pt = (ParameterizedType) toField.getGenericType();
Class<?> clz = (Class)pt.getActualTypeArguments()[0];
Object toItemObj = clz.newInstance();
if(tempItem != null) {
if(isSimpleObject(tempItem)) {
toItemObj = tempItem;
} else {
copyProperties(tempItem, toItemObj);
}
toList.add(toItemObj);
}
}
PropertyDescriptor toPd = new PropertyDescriptor(tempField.getName(), to.getClass());
Method setMethod = toPd.getWriteMethod();
setMethod.invoke(to, toList);
}
/**
* 复杂对象拷贝
* @param tempField
* @param from
* @param to
* @throws NoSuchFieldException
* @throws SecurityException
* @throws InstantiationException
* @throws IllegalAccessException
* @throws IntrospectionException
* @throws IllegalArgumentException
* @throws InvocationTargetException
*/
private static void complexCopy(Field tempField, Object from, Object to)
throws NoSuchFieldException, SecurityException, InstantiationException,
IllegalAccessException, IntrospectionException,
IllegalArgumentException, InvocationTargetException{
Field toField = getDeclaredField(to.getClass(), tempField.getName());
Object toFieldObj;
try {
toFieldObj = toField.getType().newInstance();
PropertyDescriptor toPd = new PropertyDescriptor(tempField.getName(), to.getClass());
Method setMethod = toPd.getWriteMethod();
setMethod.invoke(to, toFieldObj);
copyProperties(from, toFieldObj);
} catch (InstantiationException e) {
e.printStackTrace();
}
}
/**
* 获取类clazz的所有Field,包括其父类的Field,如果重名,以子类Field为准。
* @param clazz
* @return Field数组
*/
private static Field[] getAllField(Class<?> clazz) {
ArrayList<Field> fieldList = new ArrayList<Field>();
Field[] dFields = clazz.getDeclaredFields();
if (null != dFields && dFields.length > 0) {
fieldList.addAll(Arrays.asList(dFields));
}
Class<?> superClass = clazz.getSuperclass();
if (superClass != Object.class) {
Field[] superFields = getAllField(superClass);
if (null != superFields && superFields.length > 0) {
for(Field field:superFields){
if(!isContain(fieldList, field)){
fieldList.add(field);
}
}
}
}
Field[] result=new Field[fieldList.size()];
fieldList.toArray(result);
return result;
}
/**
* 检测Field List中是否已经包含了目标field
* @param fieldList
* @param field 带检测field
* @return
*/
private static boolean isContain(ArrayList<Field> fieldList,Field field){
for(Field temp:fieldList){
if(temp.getName().equals(field.getName())){
return true;
}
}
return false;
}
/**
* 获取field信息,如果子类中没有,则从其父类中获取
* @param object : 子类对象
* @param fieldName : 父类中的属性名
* @return 父类中的属性对象
*/
private static Field getDeclaredField(Class<?> clazz, String fieldName){
Field field = null ;
for(; clazz != Object.class ; clazz = clazz.getSuperclass()) {
try {
field = clazz.getDeclaredField(fieldName) ;
return field ;
} catch (Exception e) {
// 这里甚么都不要做!并且这里的异常必须这样写,不能抛出去。
// 如果这里的异常打印或者往外抛,则就不会执行clazz = clazz.getSuperclass(),最后就不会进入到父类中了
}
}
return null;
}
public static void main(String[] args) {
Person p = new Person("zhaichong",33);
Dept d = new Dept();
d.setCode("123");
d.setName("zc");
p.setDept(d);
List<Dept> pn = new ArrayList<Dept>();
Dept d1 = new Dept();
d1.setCode("1");
d1.setName("zc1");
pn.add(d1);
Dept d2 = new Dept();
d2.setCode("2");
d2.setName("zc2");
pn.add(d2);
Dept d3 = new Dept();
d3.setCode("3");
d3.setName("zc3");
pn.add(d3);
p.setList(pn);
PersonDest pd = new PersonDest();
try {
copyProperties(p, pd);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("---: " + pd.getAge());
}
static class Dept {
private String code;
private String name;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
static class Person{
Dept dept;
List<Dept> list = new ArrayList<Dept>();
String [] testString = new String[3];
public Person() {}
public Person(String name, int age) {
this.age=age;
this.name=name;
testString[2] = name;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
@Override
public String toString(){
return "["+this.name+" "+this.age+"]";
}
private String name;
private int age;
public List<Dept> getList() {
return list;
}
public void setList(List<Dept> list) {
this.list = list;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public Dept getDept() {
return dept;
}
public void setDept(Dept dept) {
this.dept = dept;
}
public String[] getTestString() {
return testString;
}
public void setTestString(String[] testString) {
this.testString = testString;
}
}
static class DeptDest {
private String code;
private String name;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
static class PersonDest{
public static int num = 0;
PersonDest p;
List<DeptDest> list = new ArrayList<DeptDest>();
DeptDest dept;
String [] testString = new String[3];
public PersonDest() {
num ++ ;
}
public PersonDest(String name, int age) {
this.age=age;
this.name=name;
testString[2] = name;
num ++ ;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
@Override
public String toString(){
return "["+this.name+" "+this.age+"]";
}
private String name;
private int age;
public PersonDest getP() {
return p;
}
public void setP(PersonDest p) {
this.p = p;
}
public List<DeptDest> getList() {
return list;
}
public void setList(List<DeptDest> list) {
this.list = list;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public DeptDest getDept() {
return dept;
}
public void setDept(DeptDest dept) {
this.dept = dept;
}
public String[] getTestString() {
return testString;
}
public void setTestString(String[] testString) {
this.testString = testString;
}
}
}
0 0
- POJO属性对拷(支持嵌套和继承)
- solr对嵌套(nesting)结构的支持
- iOS Json和对象互转(反射支持对象嵌套的复杂对象类型,支持基本数据类型和NSDate属性转化)
- c++笔记06---继承,公有继承,继承方式对访控属性的影响,私有继承和保护继承
- Struts学习(五):对POJO对象访问的支持
- jface databinding/PojoBindable实现对POJO对象的支持
- DOM对XML的操作,支持的方法和属性
- css继承属性和无继承属性
- 常见继承属性和非继承属性
- call()方法和属性的继承
- 访问和继承属性
- 属性封装和继承
- 8.属性和继承
- 让你的thinkphp支持嵌套继承模板
- dreamweaver随记----css的嵌套和继承
- Esper处理嵌套POJO事件
- 使用eclipse对数据库表生成pojo和映射
- css继承和非继承属性
- C++ stl map的基本操作和使用
- Socket编程实践(2) --Socket编程导引
- pygame编写的坦克游戏(六)
- 安卓开发技术:监听软键盘的显示与隐藏
- 好的架构不是设计出来的而是演进出来的
- POJO属性对拷(支持嵌套和继承)
- 机器视觉入门:K均值
- CreateThread 创建线程所引起的内存泄漏的问题
- leetcode之Maximum Subarray
- 软工及文档之大总结
- 解决方案--gloox源码编译错误
- hdu 4604 Deque(LIS)
- 洛谷1993小k的农场(差分约束系统)
- 【NGUI】Unity使用Resources加载NGUI的图片