Bean 复杂对象深度复制
目录
ShapeAnimationSerial代码: 实现 Serializable
AnimationSerial代码: 实现 Serializable
学习了Bean单个对象的深复制,那如何对Bean复杂对象类型的数据进行深度复制,有几种方式呢?
1,实现clone();
未实现引用对象的clone
ShapeAni 代码:实现clone()
public class ShapeAni implements Cloneable {
private String color;
private String type;
private Animation animation;
public ShapeAni(String color, String type, Animation animation) {
this.color = color;
this.type = type;
this.animation = animation;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public Animation getAnimation() {
return animation;
}
public void setAnimation(Animation animation) {
this.animation = animation;
}
@Override
public Object clone() {
Object clone = null;
try {
clone = super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return clone;
}
@Override
public String toString() {
return "ShapeAni{" +
"color='" + color + '\'' +
", type='" + type + '\'' +
", animation=" + animation +
'}';
}
}
Shape对象里面添加了Animation对象的引用
Animation 代码:
public class Animation {
private String showType;
private String showEffect;
public Animation(String showType, String showEffect) {
this.showType = showType;
this.showEffect = showEffect;
}
public String getShowType() {
return showType;
}
public void setShowType(String showType) {
this.showType = showType;
}
public String getShowEffect() {
return showEffect;
}
public void setShowEffect(String showEffect) {
this.showEffect = showEffect;
}
@Override
public String toString() {
return "Animation{" +
"showType='" + showType + '\'' +
", showEffect='" + showEffect + '\'' +
'}';
}
}
测试代码:
private static final String COLORS[] =
{ "红色", "粉红色", "绿色", "蓝色", "棕色", "橘色" };
private static final String SHAPES[] =
{ "圆形", "三角形", "长方形", "平行四边形", "扇形", "梯形" };
public static void main(String[] args) {
Animation animation1 = new Animation("one","fade");
Animation animation2 = new Animation("two","round");
ShapeAni shapeAni1 = new ShapeAni("红色", "蓝色",animation1);
ShapeAni shapeAni2 = (ShapeAni) shapeAni1.clone();
shapeAni2.setColor(getRandomColor());
shapeAni2.setType(getRandomShape());
System.out.println(shapeAni1.toString());
System.out.println(shapeAni2.toString());
System.out.println("=========== set all inner object ===========");
ShapeAni shapeAni3 = (ShapeAni) shapeAni1.clone();
shapeAni3.setAnimation(animation2);
System.out.println(shapeAni1.toString());
System.out.println(shapeAni3.toString());
System.out.println("=========== set part inner object ===========");
ShapeAni shapeAni4 = (ShapeAni) shapeAni1.clone();
shapeAni4.getAnimation().setShowEffect("roll");
System.out.println(shapeAni1.toString());
System.out.println(shapeAni4.toString());
}
private static String getRandomColor() {
return COLORS[(int)(Math.random()*COLORS.length)];
}
private static String getRandomShape() {
return SHAPES[(int)(Math.random()*COLORS.length)];
}
结果:
ShapeAni{color='红色', type='蓝色', animation=Animation{showType='one', showEffect='fade'}}
ShapeAni{color='绿色', type='梯形', animation=Animation{showType='one', showEffect='fade'}}
=========== set all inner object ===========
ShapeAni{color='红色', type='蓝色', animation=Animation{showType='one', showEffect='fade'}}
ShapeAni{color='红色', type='蓝色', animation=Animation{showType='two', showEffect='round'}}
=========== set part inner object ===========
ShapeAni{color='红色', type='蓝色', animation=Animation{showType='one', showEffect='roll'}}
ShapeAni{color='红色', type='蓝色', animation=Animation{showType='one', showEffect='roll'}}
从结果中,我们可以看出,如果单独操作ShapeAni里面的Animation的内容的时候,会影响到上一个内容。 在复杂对象的时候进行clone的时候,也要处理引用对象的复制
实现引用对象的clone
ShapeAnimation 代码:
public class ShapeAnimation implements Cloneable {
private String color;
private String type;
private Animation animation;
public ShapeAnimation(String color, String type, Animation animation) {
this.color = color;
this.type = type;
this.animation = animation;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public Animation getAnimation() {
return animation;
}
public void setAnimation(Animation animation) {
this.animation = animation;
}
@Override
public ShapeAnimation clone() {
ShapeAnimation clone = null;
try {
clone = (ShapeAnimation) super.clone();
clone.setAnimation(new Animation(clone.getAnimation().getShowType(), clone.getAnimation().getShowEffect()));
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return clone;
}
@Override
public String toString() {
return "ShapeAni{" +
"color='" + color + '\'' +
", type='" + type + '\'' +
", animation=" + animation +
'}';
}
}
Shape对象里面clone方法添加了Animation对象的复制,因为实例化,所以对象用了具体的类对象(public ShapeAnimation clone())。
Animation 代码:同上
这边的代码,同上面一个例子的代码
测试代码:
private static final String COLORS[] =
{ "红色", "粉红色", "绿色", "蓝色", "棕色", "橘色" };
private static final String SHAPES[] =
{ "圆形", "三角形", "长方形", "平行四边形", "扇形", "梯形" };
public static void main(String[] args) {
Animation animation1 = new Animation("one","fade");
Animation animation2 = new Animation("two","round");
// 先造一个原型
ShapeAnimation shapeAni1 = new ShapeAnimation("红色", "蓝色",animation1);
ShapeAnimation shapeAni2 = shapeAni1.clone();
shapeAni2.setColor(getRandomColor());
shapeAni2.setType(getRandomShape());
System.out.println(shapeAni1.toString());
System.out.println(shapeAni2.toString());
System.out.println("=========== set all inner object ===========");
ShapeAnimation shapeAni3 = shapeAni1.clone();
shapeAni3.setAnimation(animation2);
System.out.println(shapeAni1.toString());
System.out.println(shapeAni3.toString());
System.out.println("=========== set part inner object ===========");
ShapeAnimation shapeAni4 = shapeAni1.clone();
shapeAni4.getAnimation().setShowEffect("roll");
System.out.println(shapeAni1.toString());
System.out.println(shapeAni4.toString());
}
private static String getRandomColor() {
return COLORS[(int)(Math.random()*COLORS.length)];
}
private static String getRandomShape() {
return SHAPES[(int)(Math.random()*COLORS.length)];
}
结果:
ShapeAni{color='红色', type='蓝色', animation=Animation{showType='one', showEffect='fade'}}
ShapeAni{color='红色', type='圆形', animation=Animation{showType='one', showEffect='fade'}}
=========== set all inner object ===========
ShapeAni{color='红色', type='蓝色', animation=Animation{showType='one', showEffect='fade'}}
ShapeAni{color='红色', type='蓝色', animation=Animation{showType='two', showEffect='round'}}
=========== set part inner object ===========
ShapeAni{color='红色', type='蓝色', animation=Animation{showType='one', showEffect='fade'}}
ShapeAni{color='红色', type='蓝色', animation=Animation{showType='one', showEffect='roll'}}
如果引用对象比较复杂的话,考虑对引用对象实现clone,这样就直接复制引用
@Override
public ShapeAnimation clone() {
ShapeAnimation clone = null;
try {
clone = (ShapeAnimation) super.clone();
Animation one = (Animation) clone.getAnimation ().clone();
clone.setAnimationClone(one);
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return clone;
}
2,串行化复制;
ShapeAnimationSerial代码: 实现 Serializable
public class ShapeAnimationSerial implements Serializable {
private String color;
private String type;
private AnimationSerial animation;
public ShapeAnimationSerial(String color, String type, AnimationSerial animation) {
this.color = color;
this.type = type;
this.animation = animation;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public AnimationSerial getAnimation() {
return animation;
}
public void setAnimation(AnimationSerial animation) {
this.animation = animation;
}
@Override
public String toString() {
return "ShapeAni{" +
"color='" + color + '\'' +
", type='" + type + '\'' +
", animation=" + animation.toString() +
'}';
}
}
因为使用串行化复制,所以引用对象也要实现Serializable
AnimationSerial代码: 实现 Serializable
public class AnimationSerial implements Serializable {
private String showType;
private String showEffect;
public AnimationSerial(String showType, String showEffect) {
this.showType = showType;
this.showEffect = showEffect;
}
public String getShowType() {
return showType;
}
public void setShowType(String showType) {
this.showType = showType;
}
public String getShowEffect() {
return showEffect;
}
public void setShowEffect(String showEffect) {
this.showEffect = showEffect;
}
@Override
public String toString() {
return "Animation{" +
"showType='" + showType + '\'' +
", showEffect='" + showEffect + '\'' +
'}';
}
}
串行化代码:
import java.io.*;
import java.util.List;
import java.util.Map;
public class CloneUtils {
@SuppressWarnings("unchecked")
public static <T extends Serializable> T clone(T src){
T cloneObj = null;
try {
ObjectInputStream ois = getInputStream(src);
cloneObj = (T) ois.readObject();//返回生成的新对象
ois.close();
} catch (Exception e) {
e.printStackTrace();
}
return cloneObj;
}
@SuppressWarnings("unchecked")
public static <T> List<T> deepCopy(List<T> src) {
List<T> dest = null;
try {
ObjectInputStream ois = getInputStream(src);
dest = (List<T>) ois.readObject();
ois.close();
} catch (Exception e) {
e.printStackTrace();
}
return dest;
}
@SuppressWarnings("unchecked")
public static <K,V> Map<K,V> cloneMap(Map<K,V> src) throws IOException, ClassNotFoundException {
Map<K, V> result = null;
try {
ObjectInputStream ois = getInputStream(src);
result = (Map<K, V>)ois.readObject();
ois.close();
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
private static ObjectInputStream getInputStream(Object src) throws IOException, ClassNotFoundException {
//写入字节流
ByteArrayOutputStream out = new ByteArrayOutputStream();
ObjectOutputStream obs = new ObjectOutputStream(out);
obs.writeObject(src);
obs.close();
//分配内存,写入原始对象,生成新对象
ByteArrayInputStream ios = new ByteArrayInputStream(out.toByteArray());
return new ObjectInputStream(ios);
}
public static <T extends Serializable> T clones(T shape1) {
T cloneObj = null;
try {
ObjectInputStream ois = getInputStream(shape1);
cloneObj = (T) ois.readObject();//返回生成的新对象
ois.close();
} catch (Exception e) {
e.printStackTrace();
}
return cloneObj;
}
}
测试代码:
private static final String COLORS[] =
{ "红色", "粉红色", "绿色", "蓝色", "棕色", "橘色" };
private static final String SHAPES[] =
{ "圆形", "三角形", "长方形", "平行四边形", "扇形", "梯形" };
public static void main(String[] args) {
System.out.println("=========== Serializable ===========");
AnimationSerial animation1 = new AnimationSerial("one","fade");
AnimationSerial animation2 = new AnimationSerial("two","round");
ShapeAnimationSerial shapeAni1 = new ShapeAnimationSerial("红色", "蓝色",animation1);
ShapeAnimationSerial shapeAni2 = CloneUtils.clone(shapeAni1);
shapeAni2.setColor(getRandomColor());
shapeAni2.setType(getRandomShape());
System.out.println(shapeAni1.toString());
System.out.println(shapeAni2.toString());
System.out.println("=========== set all inner object ===========");
ShapeAnimationSerial shapeAni3 = CloneUtils.clone(shapeAni1);
shapeAni3.setAnimation(animation2);
System.out.println(shapeAni1.toString());
System.out.println(shapeAni3.toString());
System.out.println("=========== set part inner object ===========");
ShapeAnimationSerial shapeAni4 = CloneUtils.clone(shapeAni1);
shapeAni4.getAnimation().setShowEffect("roll");
System.out.println(shapeAni1.toString());
System.out.println(shapeAni4.toString());
}
private static String getRandomColor() {
return COLORS[(int)(Math.random()*COLORS.length)];
}
private static String getRandomShape() {
return SHAPES[(int)(Math.random()*COLORS.length)];
}
结果:
=========== Serializable ===========
ShapeAni{color='红色', type='蓝色', animation=Animation{showType='one', showEffect='fade'}}
ShapeAni{color='粉红色', type='梯形', animation=Animation{showType='one', showEffect='fade'}}
=========== set all inner object ===========
ShapeAni{color='红色', type='蓝色', animation=Animation{showType='one', showEffect='fade'}}
ShapeAni{color='红色', type='蓝色', animation=Animation{showType='two', showEffect='round'}}
=========== set part inner object ===========
ShapeAni{color='红色', type='蓝色', animation=Animation{showType='one', showEffect='fade'}}
ShapeAni{color='红色', type='蓝色', animation=Animation{showType='one', showEffect='roll'}}
总结:
在使用bean复制对象复制的时候,如果使用clone()方法的时候,需要注意对引用对象的处理。如果有很多引用对象的话,考虑用串行话的方式进行复制。