MST

星途 面试题库

面试题:Java中浅拷贝的实现方式及局限

请描述在Java中如何实现浅拷贝,并说明浅拷贝在处理对象引用时存在的局限性。以一个包含基本数据类型和对象引用的自定义类为例进行说明。
12.4万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

浅拷贝的实现

  1. 实现Cloneable接口:在Java中,要实现浅拷贝,类需要实现java.lang.Cloneable接口,该接口是一个标记接口,没有任何方法。
  2. 重写clone()方法Object类中有一个protected修饰的clone()方法,需要在自定义类中重写该方法,并将其访问修饰符改为public

以下是一个包含基本数据类型和对象引用的自定义类实现浅拷贝的示例:

class Address {
    private String city;

    public Address(String city) {
        this.city = city;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }
}

class Person implements Cloneable {
    private int age;
    private String name;
    private Address address;

    public Person(int age, String name, Address address) {
        this.age = age;
        this.name = name;
        this.address = address;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

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

浅拷贝在处理对象引用时的局限性

浅拷贝对于包含对象引用的成员变量,只是复制了引用地址,而不是创建新的对象。这意味着原对象和拷贝对象的相应对象引用指向同一个实际对象。

例如,继续使用上面的Person类:

public class Main {
    public static void main(String[] args) {
        Address address = new Address("Beijing");
        Person person1 = new Person(30, "Alice", address);

        try {
            Person person2 = person1.clone();

            // 修改person2的基本数据类型字段
            person2.setAge(31);
            // 修改person2的对象引用字段
            person2.getAddress().setCity("Shanghai");

            System.out.println("person1 age: " + person1.getAge());
            System.out.println("person1 city: " + person1.getAddress().getCity());
            System.out.println("person2 age: " + person2.getAge());
            System.out.println("person2 city: " + person2.getAddress().getCity());
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
    }
}

输出结果为:

person1 age: 30
person1 city: Shanghai
person2 age: 31
person2 city: Shanghai

可以看到,修改person2address对象的city属性,person1address对象的city属性也发生了改变,因为它们共享同一个Address对象的引用。这就是浅拷贝在处理对象引用时的局限性,如果需要避免这种情况,应该使用深拷贝,即对对象引用的成员变量也进行递归的拷贝。