java浅拷贝与深拷贝

java深拷贝

Java 中的数据类型分为基本数据类型和引用数据类型。对于这两种数据类型,在进行赋值操作、用作方法参数或返回值时,会有值传递和引用(地址)传递的差别。

  • 针对于8大基本数据类型而言,浅拷贝相当于深拷贝,就是将原数据的值直接赋予新的对象
  • 对于其他对象而言,浅拷贝就相当于复制一个引用,指向一块内存地址。

java浅拷贝

深拷贝,在拷贝引用类型成员变量时,为引用类型的数据成员另辟了一个独立的内存空间,实现真正内容上的拷贝。

  • 深拷贝就相当于重新开辟一块内存。将原来的数值copy一份,然后再放置在这个内存区。

以Leetcode77题而言:

class Solution {
    private List<List<Integer>> res = new ArrayList<>();
    public List<List<Integer>> combine(int n, int k) {
        dfs(n, k, 1, new ArrayList<>());
        System.out.println(res);
        return res;
    }
    
    public void dfs(int n, int k, int start, List<Integer> list) {
        // 这里面k的定义是比较精髓的,k代表的是还能组合的位数,有了这个k,使得下面的for循环能够提前剪枝,真的是精妙
        // 还要注意list作为形式参数传递的时候,传递的是一个引用,每次都是修改这个引用,就比如这里的list,虽然每次都向res中add一个list,但其实每一次add的时候都是
        // add一个引用,下面修改list的时候,相当于把这个引用指向的内存区域也给改变了,所以会变成add一样的值
        // 上面所述的传递一个引用就相当于一个浅拷贝
        if(k == 0) {
            // 这里要注意res.add与res.add(new ArrayList<>(list))之间的区别
            // res.add(list);
            res.add(new ArrayList<>(list));
            System.out.println(list);
            System.out.println("----------");
            System.out.println(res);
            return;
        }
        for(int i = start;i <= n-k+1;i++) {
            // 这里改变了list指向的引用,而不是修改list本身的值
            list.add(i);
            dfs(n, k - 1, i+1, list);
            // 这里就能改变也是list的引用,就会删除之后,就会导致最终res全部是[]  最终res = [[],[],[],[],[],[]]
            list.remove(list.size() - 1);
        }
    }
}

如果使用add(list)方法的话:

Java 从另一个数据库中复制表结构 java数据拷贝_List

如果使用add(new ArrayList(list) )的话:

Java 从另一个数据库中复制表结构 java数据拷贝_List_02

Saying Less Doing More