面向对象编程—深浅拷贝

面向对象编程—深浅拷贝,第1张

面向对象编程—深浅拷贝

目录

1.数组的拷贝

整体拷贝

部份拷贝

模拟实现数组全拷贝与部份拷贝

2.深浅拷贝的概念

浅拷贝

深拷贝

4.深浅拷贝的应用

浅拷贝

深拷贝-两种实现方式

1)递归实现的Cloneable接口

2)通过序列化来进行拷贝


1.数组的拷贝

在看深浅拷贝前,首先来看数组的拷贝:

整体拷贝

Arrays.copyOf(arr,arr.length);

import java.util.Arrays;
public class AllCopy {
    public static void main(String[] args) {
        int[] arr={1,3,5,7,9};
        int[] ret= Arrays.copyOf(arr,arr.length);//整体拷贝
        ret[0]=10;
        arr[0]=4;
        System.out.println(arrStr(arr));
        System.out.println(arrStr(ret));
    }

    private static String arrStr(int[] arr) {
        String ret="[";
        for (int i = 0; i < arr.length; i++) {
            ret+=arr[i];
            if(i!= arr.length-1) {
                ret += ",";
            }
        }
        ret+="]";
        return ret;
    }

}

结果:[4,3,5,7,9]
           [10,3,5,7,9]

分析:这里的拷贝把所有值都拷贝过来了,是属于整体拷贝。也属于深拷贝(相对来说的,它这里只有基本数据类型(即只有一层),原数组完全不影响新建数组)就是说ret[0]=10不影响原来的arr[0],arr[0]=4不影响新拷贝的数组中的ret[0]。拷贝后的数组对象确实是个新对象,开辟了新空间,只是将原数组的内容复制给新数组,这也就算属于深拷贝范畴。

部份拷贝

Arrays.copyOfRange(原数组名称,原数组起始位置,原数组结束位置)

起始位置和结束位置是左闭右开区间来取:[from,to)

import java.util.Arrays;
public class AllCopy {
    public static void main(String[] args) {
        int[] arr={1,3,5,7,9};
        int[] ret= Arrays.copyOfRange(arr,2,4);//部份拷贝
        System.out.println(arrStr(arr));
        System.out.println(arrStr(ret));
    }

    private static String arrStr(int[] arr) {
        String ret="[";
        for (int i = 0; i < arr.length; i++) {
            ret+=arr[i];
            if(i!= arr.length-1) {
                ret += ",";
            }
        }
        ret+="]";
        return ret;
    }

}

模拟实现数组全拷贝与部份拷贝
public class AllCopy {
    public static void main(String[] args) {
        int[] arr={1,3,5,7,9};
        int[] ret= arrCopy(arr);//全拷贝
        int[] str=arrCopyRange(arr,2,4);//部份拷贝
        ret[0]=10;
        System.out.println(arrStr(arr));
        System.out.println(arrStr(ret));
        System.out.println(arrStr(str));
    }

    private static int[] arrCopy(int[] arr) {
        //实现数组全拷贝
        int[] ret=new int[arr.length];
        for (int i = 0; i < arr.length; i++) {
            ret[i]=arr[i];
        }
        return ret;
    }
    private static int[] arrCopyRange(int[] arr,int start,int end) {
        //部份拷贝
        int[] str=new int[end-start];
        int j=0;
        for (int i = 0; i < arr.length; i++) {
            while(i==start&&start 

在观察数组拷贝的基础上了解深浅拷贝的概念:

2.深浅拷贝的概念 浅拷贝

通过赋值的方式进行拷贝,只是把对象的表层赋给一个新的对象,拷贝后的对象和原对象仍指向同一块空间。此时原对象内部若有引用,则改变该引用的值,新对象中该引用的值也会随之变化。(外部开辟了新的空间内部并未开辟新空间,还是原来的)

浅拷贝对基本数据类型来说是值传递,对于引用类型来说,是进行引用传递般的拷贝,并未真实的创建一个新的对象。

深拷贝

原对象的修改不会影响拷贝后的对象(内外都开辟了新的空间)

对基本数据类型来说是值传递,但是对于引用类型来讲,原对象内部若有引用,则创建一个新的对象,并复制其内成员变量等内容

【ps:什么是引用?引用就是给对象起了个名字,保存的是对象的地址】

4.深浅拷贝的应用 浅拷贝
class A{
    int num;
}
public class B implements Cloneable{
    A a=new A();
    @Override
    protected B clone() throws CloneNotSupportedException {
        return (B)super.clone();
    }

    public static void main(String[] args) throws CloneNotSupportedException {
        B b1=new B();
        B b2=b1.clone();
        System.out.println(b1==b2);
        System.out.println(b2.a.num);
        b1.a.num=100;
        System.out.println(b2.a.num);
    }
}

结果:false
           0
          100

分析:false说明b1,b2不是一个地址空间,b2实现了拷贝。而b1.a.num改变会影响b2.a.num的值,说明虽然b2是拷贝过来的,但是仍旧和b1指向同一块引用a,b1,b2中a的属性值是会同时改变的,实现了浅拷贝。

深拷贝-两种实现方式 1)递归实现的Cloneable接口

就上面浅拷贝例子而言,若要把它改成深拷贝,则在其的代码基础上,可以给A也实现Cloneable接口,即给A也实现克隆方法(都克隆-都有新空间)

class A implements Cloneable{
    int num;
    @Override
    protected A clone() throws CloneNotSupportedException {
        return (A)super.clone();
    }
}
public class B implements Cloneable{
    A a=new A();
    @Override
    protected B clone() throws CloneNotSupportedException {
        B newB=(B)super.clone();
        newB.a=a.clone();//让a也是克隆来的
        return newB;
    }
    public static void main(String[] args) throws CloneNotSupportedException {
        B b1=new B();
        B b2=b1.clone();
        System.out.println(b1==b2);
        System.out.println(b2.a.num);
        b1.a.num=100;
        System.out.println(b2.a.num);
    }
}

结果:false
          0
          0

分析:false说明b1b2是两个东西,开辟了新空间,b1中a.num改变影响不了b2中a.num,说明a也是被克隆了,开辟了新空间的,b1,b2内部包含的a确实不是一个对象,实现了深拷贝。

2)通过序列化来进行拷贝

1.序列化:将一个对象转为字符串就叫做序列化

2.将对象转为json字符串(序列化)进行拷贝,所有的序列化都是深拷贝

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5703576.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存