Java对象和集合的拷贝问题
1.今天学习了Java拷贝的问题,其实以前在学习c++的时候也知道对象的深拷贝和浅拷贝的区别,算是有一定的基础,只是在Java中没有深入,前几天在工作中遇到这个问题,当时为了简单,绕过了这个问题,现在用例子说明这个问题。
基础类Animal:
class Animal {
private String name;
private String color;
public Animal(String name, String color) {
this.name = name;
this.color = color;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public String toString(){
return "name:"+this.name+",clor:"+this.color;
}
}
测试类:
public class DemoClone {
public static void main(String[] args) {
ArrayList<Animal> list1 = new ArrayList<Animal>();
list1.add(new Animal("dog","mud"));
list1.add(new Animal("pig","black"));
ArrayList<Animal> list2 = new ArrayList<Animal>(list1);
list1.get(0).setName("dog1");
list1.get(1).setName("pig1");
System.out.println("list1 is ########################");
for(Animal temp : list1){
System.out.println(temp);
}
System.out.println("list2 is ########################");
for(Animal temp : list2){
System.out.println(temp);
}
}
}
测试结果:
list1 is ########################
name:dog1,clor:mud
name:pig1,clor:black
list2 is ########################
name:dog1,clor:mud
name:pig1,clor:black
测试评定:通过测试我们发现Java API自带的拷贝函数属于浅拷贝,当修改原来的集合list1时,拷贝的集合list2中的数据也同样发生了改变,这就是浅拷贝,原因是list1和list2指向了内存中的同一个内存单元(其中放置着Animal的对象),所以结果是上述所示
想要实现深拷贝必须让集合中的元素实现Cloneable接口,实现clone方法,这跟c++不同,c++只需要在拷贝函数中重新申请内存空间,存放原对象的内容,即可实现!
正确方法:
基础类Animal:
class Animal implements Cloneable{
private String name;
private String color;
public Animal(String name, String color) {
this.name = name;
this.color = color;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public Animal clone(){
Animal clone = null;
try{
clone = (Animal)super.clone();
}catch(Exception e){
e.printStackTrace();
}
return clone;
}
public String toString(){
return "name:"+this.name+",clor:"+this.color;
}
}
可以看出基础类Animal实现了Cloneable,实现其中clone方法,
测试类:
public class DemoClone {
/**
* @param args
*/
public static void main(String[] args) {
ArrayList<Animal> list1 = new ArrayList<Animal>();
list1.add(new Animal("dog","mud"));
list1.add(new Animal("pig","black"));
ArrayList<Animal> list2 = new ArrayList<Animal>(list1.size());
Iterator it = list1.iterator();
while(it.hasNext()){
Animal temp = (Animal)it.next();
list2.add(temp.clone());
}
list1.get(0).setName("dog1");
list1.get(1).setName("pig1");
System.out.println("list1 is ########################");
for(Animal temp : list1){
System.out.println(temp);
}
System.out.println("list2 is ########################");
for(Animal temp : list2){
System.out.println(temp);
}
}
}
测试结果:
list1 is ########################
name:dog1,clor:mud
name:pig1,clor:black
list2 is ########################
name:dog,clor:mud
name:pig,clor:black
测试评定:
符合我们的预期要求!
基础类不变,我们进行Java对象的拷贝
测试类:
public class DemoClone {
/**
* @param args
*/
public static void main(String[] args) {
Animal animal1 = new Animal("dog","mud");
Animal animal2 = animal1.clone();
animal1.setName("dog1");
System.out.println("animal1 is #######################");
System.out.println(animal1);
System.out.println("animal2 is #######################");
System.out.println(animal2);
}
}