写点什么

System

  • 2021 年 11 月 11 日
  • 本文字数:2407 字

    阅读完需:约 8 分钟

如何区分深拷贝与浅拷贝,简单点来说,就是假设 B 复制了 A,当修改 A 时,看 B 是否会发生变化,如果 B 也跟着变了,说明这是浅拷贝,拿人手短,如果 B 没变,那就是深拷贝,自食其力。

1、简单类型(深拷贝)

【一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义】
浏览器打开:qq.cn.hn/FTf 免费领取
复制代码


package com.guor.test.javaSE.collection;


import java.util.Arrays;


public class ArrayTest {


public static void main(String[] args) {


getStringArrayFromObjectArray2();


}


private static void copySelf() {


int[] ids = { 1, 2, 3, 4, 5 };


System.out.println(Arrays.toString(ids));


//System.arraycopy(src, srcPos, dest, destPos, length);


// 把从索引 0 开始的 2 个数字复制到索引为 3 的位置上


System.arraycopy(ids, 0, ids, 3, 2);


System.out.println(Arrays.toString(ids));//[1, 2, 3, 1, 2]


}


private static void copyToOther() {


int[] ids = { 1, 2, 3, 4, 5 };


//将数据的索引 1 开始的 3 个数据复制到目标的索引为 0 的位置上


int[] other = new int[5];


System.arraycopy(ids, 1, other, 0, 3);


System.out.println(Arrays.toString(ids));//[1, 2, 3, 4, 5]深复制


System.out.println(Arrays.toString(other));//[2, 3, 4, 0, 0]


}


//如果是类型转换问题,获取整形


private static void getIntegerArrayFromObjectArray() {


Object[] obj1 = { 1, 2, 3, "4", "5" };


Integer[] obj2 = new Integer[5];


try {


System.arraycopy(obj1, 0, obj2, 0, obj1.length);


} catch (Exception e) {


System.out.println("transfer exception:"+e);


}


System.out.println(Arrays.toString(obj1));


System.out.println(Arrays.toString(obj2));


}


//获取 Object 数组中的字符串类型数据


private static void getStringArrayFromObjectArray1() {


Object[] obj3 = { 1, 2, 3, "4", "5" };


String[] obj4 = new String[5];


try {


System.arraycopy(obj3, 2, obj4, 2, 3);


} catch (Exception e) {


//transfer exception:java.lang.ArrayStoreException


System.out.println("transfer exception:"+e);


}


System.out.println(Arrays.toString(obj3));


//[null, null, null, null, null]


System.out.println(Arrays.toString(obj4));


}


//获取 Object 数组中的字符串类型数据


private static void getStringArrayFromObjectArray2() {


Object[] obj3 = { 1, 2, 3, "4", "5" };


String[] obj4 = new String[5];


try {


System.arraycopy(obj3, 3, obj4, 3, 2);


} catch (Exception e) {


System.out.println("transfer exception:"+e);


}


System.out.println(Arrays.toString(obj3));


//[null, null, null, 4, 5]


System.out.println(Arrays.toString(obj4));


obj3[3] = "zhangssan";


System.out.println("查看是浅复制还是深复制~~~~~");


System.out.println(Arrays.toString(obj3));


System.out.println(Arrays.toString(obj4));


}


}


只有普通数据类型和 String 类型是深拷贝!?


2、二维数组(浅拷贝)

//二维数组


public static void twoArray() {


int[] arr1 = {1, 2};


int[] arr2 = {3, 4};


int[] arr3 = {5, 6};


int[][] src = new int[][]{arr1, arr2, arr3};


print("原始模样:", src);


int[][] dest = new int[3][];


System.arraycopy(src, 0, dest, 0, 3);


System.out.println("改变前");


print("src = ", src);


print("dest = ", dest);


//原数组改变后观察新数组是否改变,改变->浅复制,不改变->深复制


src[0][0] = -1;


System.out.println("改变后");


print("src = ", src);


print("dest = ", dest);


}


//二维数组 toString()


private static void print(String string, int[][] arr) {


System.out.print(string);


for (int[] a : arr) {


for (int i : a) {


System.out.print(i + " ");


}


System.out.print(",");


}


System.out.println();


}


二维数组属于浅拷贝,原始数组改变后,复制的数据也发生了改变!?


3、对象复制(深拷贝?)


四、System.arraycopy 是不安全的



1、代码实例

多线程对数组进行复制,看 System.arraycopy 线程是否安全?


package com.guor.test.javaSE.collection;


import java.util.Arrays;


import java.util.concurrent.locks.Condition;


import java.util.concurrent.locks.ReentrantLock;


public class ArrayTest2 {


private static int[] arrayOriginal = new int[1024 * 1024 * 10];


private static int[] arraySrc = new int[1024 * 1024 * 10];


private static int[] arrayDest = new int[1024 * 1024 * 10];


private static ReentrantLock lock = new ReentrantLock();


private static void modify() {


for (int i = 0; i < arraySrc.length; i++) {


arraySrc[i] = i + 1;


}


}


private static void copy() {


System.arraycopy(arraySrc, 0, arrayDest, 0, arraySrc.length);


}


private static void init() {


for (int i = 0; i < arraySrc.length; i++) {


arrayOriginal[i] = i;


arraySrc[i] = i;


arrayDest[i] = 0;


}


}


private static void doThreadSafeCheck() throws Exception {


for (int i = 0; i < 100; i++) {


System.out.println("run count: " + (i + 1));


init();


Condition condition = lock.newCondition();


new Thread(new Runnable() {


@Override


public void run() {


lock.lock();


condition.signalAll();


lock.unlock();


copy();


}


}).start();


lock.lock();


// 这里使用 Condition 来保证拷贝线程先已经运行了.


condition.await();


lock.unlock();


Thread.sleep(2); // 休眠 2 毫秒, 确保拷贝操作已经执行了, 才执行修改操作.


modify();


// 如果 System.arraycopy 是线程安全的, 那么先执行拷贝操作, 再执行修改操作时, 不会影响复制结果, 因此 arrayOriginal 必然等于 arrayDist;


if (!Arrays.equals(arrayOriginal, arrayDest)) {


throw new RuntimeException("System.arraycopy is not thread safe");


}


}


}


public static void main(String[] args) throws Exception {

评论

发布
暂无评论
System