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

 

posted @ 2017-07-23 14:24  Mr.袋鼠  阅读(197)  评论(0编辑  收藏  举报