2023.9 - java - 浅拷贝

与 js的浅拷贝不同:

在 JavaScript 中, Object.assign() 或 spread 运算符等方法可以实现浅拷贝,但只针对对象的第一层属性进行复制。如果一个对象只包含基本数据类型的属性,那么对浅拷贝出来的对象进行修改不会影响原始对象,因为它们拥有不同的内存地址。但是如果拷贝的对象包含引用类型的属性(如数组、对象等),那么拷贝出来的对象和原始对象会引用同一个内存地址,因此如果在拷贝出来的对象上修改引用类型属性,原始对象也会受到影响。

而在 Java 中,浅拷贝通常无论对象是否只有一层,都只是复制了对象的引用,因此当对象包含引用类型的属性时,浅拷贝出来的对象和原始对象也会引用同一个内存地址,原始对象的修改会影响浅拷贝出来的对象。由于 Java 中基本类型和引用类型都需要使用 new 进行初始化,所以浅拷贝并不会将基本类型的数据复制到新的对象中。

Java 中基本类型和引用类型都需要使用 new 进行初始化,所以浅拷贝并不会将基本类型的数据复制到新的对象中"。

class Person {
    String name;
    
    Person(String name) {
        this.name = name;
    }
}

public class Main {
    public static void main(String[] args) {
        String originalName = "John";
        String clonedName = originalName;
        
        System.out.println("Original Name: " + originalName);
        System.out.println("Cloned Name: " + clonedName);
        
        clonedName = "Mike";
        
        System.out.println("Original Name: " + originalName);
        System.out.println("Cloned Name: " + clonedName);
        
        Person originalPerson = new Person("John");
        Person clonedPerson = originalPerson;
        
        System.out.println("Original Person Name: " + originalPerson.name);
        System.out.println("Cloned Person Name: " + clonedPerson.name);
        
        clonedPerson.name = "Mike";
        
        System.out.println("Original Person Name: " + originalPerson.name);
        System.out.println("Cloned Person Name: " + clonedPerson.name);
    }
}

在上述代码中,我们首先定义了一个名为 originalName 的字符串变量,并将其赋值为 "John"。然后,我们将 originalName 的值赋给 clonedName 变量。输出结果显示 originalNameclonedName 的值都是 "John"。

接着,我们将 clonedName 的值修改为 "Mike"。输出结果显示 originalName 的值仍然是 "John",而 clonedName 的值变成了 "Mike"。这是因为字符串是不可变类型,所以在将 originalName 的值赋给 clonedName 时,实际上是创建了一个新的字符串对象。

然后,我们定义了一个名为 Person 的类,其中包含一个 name 字符串属性。在 main 函数中,我们实例化了一个 originalPerson 对象,并将其赋给 clonedPerson 变量。输出结果显示 originalPersonclonedPersonname 属性值都是 "John"。

然后,我们将 clonedPersonname 属性值修改为 "Mike"。输出结果显示 originalPersonclonedPersonname 属性值都变成了 "Mike"。这是因为对象是引用类型,originalPersonclonedPerson 实际上指向了同一个对象,修改其中一个对象的属性会影响到另一个对象。

因此,上述代码示例说明了基本类型和引用类型在赋值时的区别。在浅拷贝中,基本类型的数据并不会被复制到新的对象中,而是共享同一份数据,而引用类型的数据则会被共享。

 

2023.9 - java - 浅拷贝_第1张图片

 【这是因为字符串是不可变类型,所以在将 originalName 的值赋给 clonedName 时,实际上是创建了一个新的字符串对象。】 这句话解释了为什么 【25行代码修改了Apple为Orange】但是arrarList却米有受到影响。【由于String 对象是一旦声明不可变的,所以当arrarList1修改的时候,arrayList1.get(0)的对象引用已经指向了一个新的对象】。所以 arrayList.get(0) 还是原来的值。

         myClass m = new myClass("王明");
            ArrayList list = new ArrayList<>();
        list.add(m);
        ArrayList list2 = (ArrayList) list.clone();
        list2.get(0).a = "李明";
        System.out.println(list.get(0).a);
        System.out.println(list2.get(0).a);   
        
         为什么 需要  (ArrayList) 强制转型


在对 list.clone() 进行调用时,返回的是一个 Object 类型的对象,而不是 ArrayList 类型的对象。这是因为 clone() 方法返回的是一个浅拷贝的对象,其继承自 Object 类。因此,为了将其转换为 ArrayList 类型,需要进行强制类型转换。

在上述代码中,我们创建了一个名为 myClass 的类,其中包含一个名为 a 的字符串属性。首先,我们创建了一个 myClass 对象 m,并将其添加到 ArrayList 类型的列表 list 中。然后,我们使用 clone() 方法创建了一个 list2 的副本对象。

注意,clone() 方法返回的是一个浅拷贝的对象,即 list2 和 list 引用的是同一个内存地址,其中的元素也是共享的。因此,当我们在 list2 中修改元素的属性值时,list 中对应的元素也会受到影响。

为了避免编译器产生警告,我们使用了 (ArrayList) 进行强制类型转换,将返回的 Object 类型对象转换为 ArrayList 类型。

 

你可能感兴趣的:(2023-java,java,开发语言)