参考的文章地址如下:
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