java clone
参考的文章地址如下:
http://blog.csdn.net/zzp_403184692/article/details/8184751
写的很详细,而且有例子,收货很多。
看到别人提到clone,在此记录一下学习情况。
首先要明确java的参数的传递方式。分为两种,一种是值传递,一种是引用传递。
(1)java的参数传递都是按照值传递:按值传递 传递的是值的拷贝;按引用传递,传递的是对象引用的地址值,所以统称为值传递。
(2)java中只有基本数据类型和String a = “bbb”; 这种直接使用双引号定义字符串方式的 String 是值传递,其余的都是引用传递。
深拷贝和浅拷贝
浅拷贝,直接将源对象的引用给新对象;深拷贝,将源对象的值给新对象。
接下来进入文章主题,clone。
在java中,以下的代码很常见,
例子1,如下。
import org.apache.log4j.Logger;
public class CloneDemo {
static Logger logger = Logger.getLogger(CloneDemo.class);
public static void main(String[] args) {
Person p = new Person(20, "lee");
Person p1 = p;
logger.info("p " + p);
logger.info("p " + p1);
logger.info("p = p1 ?" + (p == p1));
logger.info("p.age" + p.getAge());
logger.info("p.name" + p.getName());
logger.info("p1.age" + p1.getAge());
logger.info("p1.name" + p1.getName());
p.setAge(80);
p.setName("batman");
logger.info("p.age" + p.getAge());
logger.info("p.name" + p.getName());
logger.info("p1.age" + p1.getAge());
logger.info("p1.name" + p1.getName());
}
}
对象p1的引用指向了p,两者的引用是一样的,都指向一个对象。执行结果如下:
[com.lee.demo.CloneDemo] - p com.lee.demo.Person@14989ff
[com.lee.demo.CloneDemo] - p com.lee.demo.Person@14989ff
[com.lee.demo.CloneDemo] - p = p1 ?true
[com.lee.demo.CloneDemo] - p.age20
[com.lee.demo.CloneDemo] - p.namelee
[com.lee.demo.CloneDemo] - p1.age20
[com.lee.demo.CloneDemo] - p1.namelee
[com.lee.demo.CloneDemo] - p.age80
[com.lee.demo.CloneDemo] - p.namebatman
[com.lee.demo.CloneDemo] - p1.age80
[com.lee.demo.CloneDemo] - p1.namebatman
说明一下,Person p1 = p; 现在是对p p1的引用进行了操作,所以这是操作p,p1的值会发生变化。
例子2,如下。
接下来使用clone()来复制对象
public class CloneDemo02 { static Logger logger = Logger.getLogger(CloneDemo02.class); public static void main(String[] args) throws CloneNotSupportedException { Person p = new Person(23, "zhang"); Person p1 = (Person) p.clone(); logger.info("p " + p); logger.info("p " + p1); logger.info("p = p1 ?" + (p == p1)); logger.info("p.age " + p.getAge()); logger.info("p.name " + p.getName()); logger.info("p1.age " + p1.getAge()); logger.info("p1.name " + p1.getName()); p.setAge(80); p.setName("batman"); logger.info("p.age " + p.getAge()); logger.info("p.name " + p.getName()); logger.info("p1.age " + p1.getAge()); logger.info("p1.name " + p1.getName()); } }
执行结果如下:
[com.lee.demo.CloneDemo02] - p com.lee.demo.Person@14989ff [com.lee.demo.CloneDemo02] - p com.lee.demo.Person@1099f62 [com.lee.demo.CloneDemo02] - p = p1 ?false [com.lee.demo.CloneDemo02] - p.age 23 [com.lee.demo.CloneDemo02] - p.name zhang [com.lee.demo.CloneDemo02] - p1.age 23 [com.lee.demo.CloneDemo02] - p1.name zhang
[com.lee.demo.CloneDemo02] - p.age 80 [com.lee.demo.CloneDemo02] - p.name batman [com.lee.demo.CloneDemo02] - p1.age 23 [com.lee.demo.CloneDemo02] - p1.name zhang
需要强调一些东西。clone() 是它自身Person对象的克隆,所以,p和p1的引用不是一个。此外用于,Person中的name,age的类型是String,int,也就是primitive,因此改变p后,p1不会随之变化。
例子3,如下。
public class Account implements Cloneable {
Person person;
long balance;
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class Person implements Cloneable {
Person (int age, String name) {
this.age = age;
this.name = name;
}
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
private String name;
@Override
protected Object clone() throws CloneNotSupportedException {
return (Person)super.clone();
}
}
1 public class CloneDemo03 { 2 3 static Logger logger = Logger.getLogger(CloneDemo03.class); 4 public static void main(String[] args) throws CloneNotSupportedException { 5 // TODO Auto-generated method stub 6 7 Person p = new Person(23, "zhang"); 8 Account account = new Account(); 9 account.balance = 1000; 10 account.person = p; 11 Account copy = (Account) account.clone();
//balance因为是primitive,所以copy和原型是相等且独立的。 12 logger.info("copy.balance equals account.balance " + (copy.balance == account.balance)); 13 copy.balance = 2000; 14 logger.info("copy.balance equals account.balance " + (copy.balance == account.balance)); 15
//person因为是引用类型,所以copy和原型的引用是同一的。 16 logger.info("copy.person equals account.person " + (copy.person == account.person)); 17 copy.person.setName("babyBoss"); 18 logger.info(account.person.getName()); 19 logger.info("copy.person.name equals account.person.name " + (copy.person.getName() == account.person.getName())); 20 } 21 22 }
[com.lee.demo.CloneDemo03] - copy.balance equals account.balance true
[com.lee.demo.CloneDemo03] - copy.balance equals account.balance false
[com.lee.demo.CloneDemo03] - copy.person equals account.person true
[com.lee.demo.CloneDemo03] - babyBoss
[com.lee.demo.CloneDemo03] - copy.person.name equals account.person.name true
primitive的确做到了相等且隔离,引用类型仅仅是复制了一下引用,copy和原型引用的东西是一样的,这就是所谓的浅拷贝。
文章中,有些地方不是好理解,慢慢思考,跟着做例子。一步步来吧!我也是弄了很长时间。共勉。
至于深拷贝怎么弄,我自己弄得不是很明白,推荐一篇文章,有兴趣的小伙伴们自己研究一下。
http://blog.csdn.net/it_man/article/details/5744351