java clone 闡述

1、爲什麼要clone

當一個對象需要被多人操作,但是又不相互影響,需要保持原對象的狀態,這時就會克隆出許多不同的對象。

2、new 對象和 clone 對象的區別

new 操作 本質是操作內存。程序在執行new操作的時候,首先看到的是new
操作符後面的類型,因爲知道了類型,才能知道要分配多大的內存空間。分配完內存後,在調用構造函數,填充對象的各個域,這一步叫做對象的初始化。構造方法創建完成之後,可以吧他的引用(地址)發佈到外部,就可以在外部引用操縱這個對象。
clone 在第一步 和new 相似,都是分配內存,調用clone 方法時,分配的內存和原對象(調用clone方法的原對象),然後再使用對象中對應的各個域,填充新的對象的域,填充完成後,clone 方法返回,一個新的相同的對象被創建,同樣可以把新的對象那個的引用發佈到外部。

3、clone 對象的使用

1) 我們 先看 一下 賦值引用;
package com.example.lum.myapplication;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Person testObjectOne;
        Person testObjectTwo;
        testObjectOne = new Person(28,"lu"); //新建 一個對象 one
        testObjectTwo = testObjectOne;  //將 one 賦值給 Twos
        System.out.println("``````````````");
        System.out.println(testObjectOne);
        System.out.println(testObjectTwo);
        System.out.println("``````````````");
    }

  class Person  {
        private  int  age;
        private  String  name ;
        public  Person(int age,String name){
            this.age = age;
            this.name = name;
        }
        @Override
        protected Object clone() throws CloneNotSupportedException {
            return (Person)super.clone();
        }
    }


}

log 顯示:

在這裏插入圖片描述

我們可以看到打印的地址值是相同的,那肯定是一個對象。
testObjectOne,testObjectTwo 只是引用而已,都指向一個相同的對象 Person。
可以把這種現象叫做引用的複製:

在這裏插入圖片描述

2)下面我們看一下克隆一個對象:

這個時候 Person 類需要繼承 Cloneable 實現 clone 接口

package com.example.lum.myapplication;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        try {
        Person testObjectOne;
        Person testObjectTwo;
        testObjectOne = new Person(28,"lu"); //新建 一個對象 one
        testObjectTwo = (Person) testObjectOne.clone();  //將 one 克隆Two
        System.out.println("``````````````");
        System.out.println(testObjectOne);
        System.out.println(testObjectTwo);
        System.out.println("``````````````");

        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
    }

  class Person implements Cloneable {
        private  int  age;
        private  String  name ;
        public  Person(int age,String name){
            this.age = age;
            this.name = name;
        }
        @Override
        protected Object clone() throws CloneNotSupportedException {
            return (Person)super.clone();
        }
    }
}

log顯示:
在這裏插入圖片描述
我們可以看到
在這裏插入圖片描述

4、clone 分爲 淺拷貝 和 深拷貝

就像我們的類一樣,裏面有 變量,age ,name 。
age 是基礎數據類型,在clone 時直接 將一個4字節數值拷貝過來,
name 是String 類型,它是一個引用,指向String 對象。那麼對它的clone有兩種,一種是將引用拷給新的對象,一種是將最它指向的字符串對象clone出來,賦值給新的對象。
這兩種方式 一個是淺拷貝,一個是深拷貝

1) 淺拷貝

在這裏插入圖片描述

2)、深拷貝

在這裏插入圖片描述

3)、淺拷貝示例

我們上面代碼就是淺拷貝示例,我們比較下拷貝對象裏的 name 地址 和 原對象地址是否一樣

package com.example.lum.myapplication;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        try {
        Person testObjectOne;
        Person testObjectTwo;
        testObjectOne = new Person(28,"lu"); //新建 一個對象 one
        testObjectTwo = (Person) testObjectOne.clone();  //將 one 賦值給 Twos
        System.out.println("``````````````");
        System.out.println(testObjectOne.getName());
        System.out.println(testObjectTwo.getName());
        System.out.println((testObjectOne.getName() == testObjectTwo.getName()));

        System.out.println("``````````````");

        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
    }

    class Person implements Cloneable {
        private  int  age;
        private  String  name ;
        public  Person(int age,String name){
            this.age = age;
            this.name = name;
        }
        public int  getAge(){
            return  this.age;
        }

        public  String   getName (){
            return  this.name;
        }

        @Override
        protected Object clone() throws CloneNotSupportedException {
            return (Person)super.clone();
        }
    }

}

打印的 log:

在這裏插入圖片描述

4)、深拷貝的例子

我們在年齡,姓名,之上添加一個靈魂

package com.example.lum.myapplication;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

import java.net.Socket;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        try {
        Person testObjectOne;
        Person testObjectTwo;
        testObjectOne = new Person(28,"lu",new Soul()); //新建 一個對象 one
        testObjectTwo = (Person) testObjectOne.clone();  //將 one 賦值給 Twos
        System.out.println("``````````````");
        System.out.println(testObjectOne.getName());
        System.out.println(testObjectTwo.getName());
        System.out.println((testObjectOne.getName() == testObjectTwo.getName()));
        System.out.println(testObjectOne.getSoul());
        System.out.println(testObjectTwo.getSoul());
        System.out.println((testObjectOne.getSoul() == testObjectTwo.getSoul()));
        System.out.println("``````````````");

        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
    }

    class Person implements Cloneable {
        private  int  age;
        private  String  name ;
        private Soul soul;
        public  Person(int age,String name, Soul soul){
            this.age = age;
            this.name = name;
            this.soul = soul;
        }
        public int  getAge(){
            return  this.age;
        }

        public  String   getName (){
            return  this.name;
        }


        public  Soul   getSoul (){
            return  this.soul;
        }

        @Override
        protected Object clone() throws CloneNotSupportedException {
            Person person = (Person) super.clone();  // 回調 clone 方法 新建Person 對象
            person.soul = (Soul) soul.clone(); //同時 對象 裏的 靈魂對象 clone 自身父類
            return person;
        }
    }

//新建靈魂對象 同時 也 添加 Cloneable 接口
    class  Soul  implements  Cloneable{
        public Soul(){}
        @Override
        protected Object clone() throws CloneNotSupportedException {
            return (Soul)super.clone();
        }
    }
}

log :
在這裏插入圖片描述

我們可以看到 靈魂的對象他們clone 前後的地址是不一樣的。
就是深克隆 ,克隆的對象裏的對象也要克隆。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章