(1) 大家在用SSH框架开发网站时应该有这样的经历:
jsp页面的值是通过struts的Action注入的POJO实体类属性来赋值的:
例如:页面有<input type="text" name="users.name" value="${users.name}"/>...等等控件,他们的值都进行了类似的绑定。那么在对应的Action中必然有Users类的对象users与之对应,且有setter和getter方法。
那么关键来了,这个时候,我们页面要做一个修改功能,通常我们的做法是:
1.1 先通过Hibernate的 load(类.class,主键值) 或者get(类.class,主键值)得到欲修改的对象的句柄,我们暂且把他取名为entity;
1.2 然后就是要把页面上不为空(null)的控件的值填充到entity中,这里也就是把users中不为空的属性的值覆盖掉entity里的值;
我们通常的做法是:
if(users.name!=null){
entity.name=users.name;
}
if(users.email!=null){
entity.email=users.email;
}
.
.
.
这个要是POJO实体Users类只有几个字段那也就罢了,可是要是不幸的有三四十个字段,那绝对能搞死你呀!!!
怎么办?
(2) 这个方法是这样的,有时候你会调用一个类的方法,这个方法呢有一个对象参数,这个对象在调用方法里要使用,在被调用方法里也要使用而且不能冲突,啥意思?看例子:
public Role role = new Role();
public void aMethod(Users users) {
users.setName("凌空幻月");
//这里我假设要把这个users对象传到Role类的字段Users users赋值
role.setUsers(users);
}
public void bMethod(){
Users users = new Users();
users.setName("张三");
users.setSex("男");
users.setAddress("湖南岳阳");
//此处省略若干setter方法
//这里调用aMethod方法
this.aMethod(users);
//程序运行到这都没问题,但有时候吧,人就喜欢偷点懒,哈哈,做完上面这些,下面有个查询操作要做,而这个查询条件呢除了姓名外,
//其他的都和上面的一样,实在是不想再写一遍那无聊的set方法了,于是就想:
Users users2 = users;
users2.setName("夕阳醉晚亭");
//查询操作
.
.
.
String roleUserName = role.getUser().getName();
}
这样一看,自己得意了,又省代码了.
可是一运行问题来了:
这里悲催的发现,roleUserName的值已经不是在aMethod方法里赋值的“凌空幻月”了,而是“夕阳醉晚亭”!!
疯了,开始骂娘了,这什么呀,我明明是把’夕阳醉晚亭‘赋值给了users2的,怎么users的Name也变了?
额,呵呵,其实这是新人常犯的错误啦:
Users users2 = users;这里这样一赋值,其实users2和users所操作的对象是同一个,这里我们要纠正一个知识性错误,users和users2本身不是对象,他们只是对象的句柄,句柄是什么?举个例子:
如果说对象是电视机,那么句柄就是遥控器。
这里也可以把,users和users2看做是遥控器,而他们操作的'电视机'却是同一个,即同一个对象。
所以才会出现上面问题。
呼~~解释完了,那么怎么能让我们偷这个懒呢,呵呵,我们要是能照这之前的电视机copy一个,然后,我用copy的电视机的遥控器换台就不影响之前的'电视机'了,怎么实现?
哈哈,啥都不说了,上代码:
/****************************************************************************
* @projectName: SmallGrantsManager
* @packageName: com.sys.small.common
* @author: chenqz
* @fileName: ObjectCopyUtil.java
* @createTime: 2012-9-5
* @E-Mail: chenqz5633@163.com
****************************************************************************/
package com.sys.small.common;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class ObjectCopyUtil<T>{
/**把oldClass对象中的不为空的字段的值复制到newClass
* @param oldClass
* @param newClass
* @throws Exception
* @author chenqz
* @date 2012年9月5日 17:41:07
*/
public void copyNoNullParams(T oldClass,T newClass) throws Exception{
//得到oldClass对象所属类的所以字段的集合
Field[] fields = oldClass.getClass().getDeclaredFields();
for(Field field:fields){
//这里说明下,给xxx字段添加属性即setter和getter方法时,方法的名称一定要是setXxx()和getXxx(),不然那就没法做了
String attributeName = field.getName(); //获取属性的名字
String firstName = attributeName.substring(0,1).toUpperCase(); //获取第一个字母
String getMethodName = "get"+firstName+attributeName.substring(1); //获取getter方法的名称
String setMethodName = "set"+firstName+attributeName.substring(1); //获取setter方法的名称
Method getMethod = oldClass.getClass().getMethod(getMethodName, new Class[]{}); //获取getter方法
Method setMethod = oldClass.getClass().getMethod(setMethodName,new Class[]{field.getType()});//获取setter方法
//大家可能对上面的new Class[]{}很疑惑,是这样的,这是一个空的Class数组,这个能看明白吧,那么{}里面存放的就是Class,他表示这个方法的参数类型。
//如上的setMethod:
// ,new Class[]{field.getType()}表示setter方法的第一个参数的类型同field一样
//下面就是关键了:首先调用oldClass中getMethod,得到值,然后判断值是否为空,不为空再赋值给newClass对象的对应字段
Object getValue = getMethod.invoke(oldClass, new Object[]{});
if(getValue!=null){
setMethod.invoke(newClass, new Object[]{getValue});
}
}
}
/**完全赋值一个类的实例
* @param object
* @return
* @throws Exception
* @author chenqz
* @date 2012年9月5日 17:41:42
*/
public T copy(T object) throws Exception {
Class<?> classType = object.getClass();
Field[] fields = classType.getDeclaredFields();
/*
* 创建此 Class 对象所表示的类的一个新实例。如同用一个带有一个空参数列表的 new 表达式实例化该类。
*/
Constructor<?> constructor = classType.getDeclaredConstructor();
Object consObj = constructor.newInstance();
for (Field field : fields) {
String attributeName = field.getName(); // 获取属性的名字
String firstName = attributeName.substring(0, 1).toUpperCase();
String getMethodName = "get" + firstName + attributeName.substring(1);
String setMethodName = "set" + firstName + attributeName.substring(1);
Method getMethod = classType.getMethod(getMethodName, new Class[] {});
Method setMethod = classType.getMethod(setMethodName, new Class[] { field.getType() });
Object getValue = getMethod.invoke(object, new Object[] {});
setMethod.invoke(consObj, new Object[] { getValue });
}
return (T) consObj;
}
public static void main(String[] args) {
Users u1 = new Users();
u1.setUserName("凌空幻月");
Users u2 = new Users();
u2.setEmail("chenqz5633@163.com");
ObjectCopyUtil<Users> oc = new ObjectCopyUtil<Users>();
try {
oc.copyNoNullParams(u1, u2);
System.out.println("这里的值还是原来的u2的email的值:"+u2.getEmail());
System.out.println("这里的值把原来的u1的UserName的值赋值过来了:"+u2.getUserName());
Users u3 = oc.copy(u1);
System.out.println(u1);
System.out.println(u3);
//上面的打印结果为:
//com.sys.small.common.Users@1fb8ee3
//com.sys.small.common.Users@61de33
//说明他们操作的已经不是同一个对象了
} catch (Exception e) {
e.printStackTrace();
}
}
}
class Users{
private String userName;
private String email;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
分享到:
相关推荐
Java中的对象复制与克隆是程序开发中常见的需求,主要用于创建一个对象的副本,而不会影响原始对象的状态。这里主要讨论两种类型的对象拷贝:浅拷贝和深拷贝。 浅拷贝,也称为表面拷贝,是创建一个新的对象,然后将...
标题中的“java对象复制克隆”主要涉及的是深拷贝,这是一种创建一个新对象的方式,新对象不仅复制了原对象的所有属性,还复制了嵌套的对象引用,使得修改复制后的对象不会影响到原始对象。 **浅拷贝**:在浅拷贝中...
在Java编程语言中,对象克隆是一种创建与现有对象具有相同数据的新对象的过程。这个过程在需要复制对象的所有属性而不创建新类型实例时非常有用。本文将深入探讨Java中的对象克隆,包括其原理、实现方式以及注意事项...
在深克隆中,新的对象和原始对象是完全独立的,如果原始对象的成员变量发生变化,那么新的对象不会受到影响。 在 Java 中,实现深克隆可以通过序列化(Serialization)和反序列化(Deserialization)来实现。这是...
在Java编程语言中,对象克隆是一种创建一个与原对象具有相同数据的新对象的过程。对象克隆主要用于复制或备份对象,以便在不干扰原始对象的情况下对其进行修改或操作。本篇文章将详细探讨Java中的对象克隆及其实现...
在Java编程语言中,克隆是一种创建对象副本的方法,它允许我们复制一个对象并拥有一个完全独立的新实例,而不是仅仅引用原始对象。克隆技术在处理复杂数据结构、避免对象共享以及实现对象复制等方面有着广泛的应用。...
java的两种深度克隆方法,1cloneTest是用Cloneable接口的clone方法实现(对象必须要实现cloneable接口).2cloneSerialize.java是用对象流写对象到byte数组中,然后从byte数组中取得对象.(对象必须要实现serializble接口)
总之,Java中的深度克隆是通过复制对象及其引用的对象来创建一个完全独立的新对象的过程。可以通过实现`Serializable`接口并进行序列化和反序列化,或者使用自定义的拷贝构造函数和工厂方法来实现。选择哪种方法取决...
深克隆则会创建一个新的对象,并且所有引用类型的成员变量都会被递归地复制,这样即使原始对象和克隆对象之间有相互引用,它们也是完全独立的。深克隆确保了即使原始对象发生改变,克隆对象也不会受到影响。 实现深...
例如,假设我们有一个 Employee 对象,通过浅克隆可以生成一个新的 Employee 对象,但是这两个对象共享同一个 Date 对象的 reference,这样克隆类就和原始类共享了一部分信息,这是不利的。 深克隆(Deep Clone)则...
在Java编程语言中,克隆是一种创建对象副本的方法,它允许我们复制一个对象并得到一个与原对象相同但独立的新对象。克隆分为两种主要类型:深克隆和浅克隆。理解这两种克隆的区别是Java面向对象编程中的重要概念。 ...
在Java编程语言中,克隆(Clone)机制是一种创建对象副本的方法,它允许开发者创建一个已有对象的新实例,这个新实例与原对象具有相同的属性值,但却是两个独立的对象,彼此的操作不会互相影响。克隆机制在某些情况...
在Java编程语言中,克隆和序列化是两个重要的概念,它们在数据处理和对象管理中扮演着关键角色。下面将分别对这两个概念进行详细解释,并结合实例和源代码进行阐述。 **一、克隆** 1. **克隆定义**:克隆是指创建...
1. **确保数据独立性**:深度克隆可以创建出与原对象完全独立的新对象,即使修改新对象也不会影响到原对象。 2. **避免副作用**:在多线程环境下,深度克隆有助于避免因共享对象而导致的数据竞争问题。 3. **提高...
Java对象的深度克隆是一种创建一个新对象的过程,该新对象与原始对象具有相同的数据,但两者之间相互独立,修改其中一个对象不会影响另一个。在Java中,深度克隆与浅克隆的区别在于处理对象内部引用的复杂性。浅克隆...
在Java编程语言中,克隆是创建一个对象副本的过程,这个副本与原对象有相同的属性值,但作为不同的对象存在。克隆分为两种主要类型:浅克隆(Shallow Clone)和深克隆(Deep Clone)。这篇博客文章将探讨这两种克隆...
深入了解Java对象的克隆 Java 对象的克隆是 Java 编程语言中一个重要的概念,它允许开发者创建对象的副本,避免了对象之间的相互影响。在本文中,我们将深入了解 Java 对象的克隆,了解何时需要使用克隆,如何实现...