21xrx.com
2024-11-08 22:01:06 Friday
登录
文章检索 我的文章 写文章
「Java」如何复制对象?附代码案例
2023-06-16 22:57:47 深夜i     --     --
Java 对象拷贝 Cloneable 序列化

在Java中,当我们需要复制一个对象时,可以使用对象拷贝(Object Cloning)的方式来实现。对象拷贝可以让我们通过创建一个新对象来复制现有对象的状态,而不是共享同一对象实例。

Java提供了两种实现对象拷贝的方式:

1. 实现Cloneable接口并重写clone()方法

2. 使用序列化(Serialization)

下面分别对这两种方式进行介绍。

1. 实现Cloneable接口并重写clone()方法

首先,让我们来看一下如何使用Cloneable接口来实现对象拷贝。Cloneable接口是一个标记接口,表示该类可以被克隆。在使用时,需要重写clone()方法,以便在实例化新对象时拷贝现有对象的状态。

下面是一个示例:


public class Person implements Cloneable {

  private String name;

  private int age;

  private Address address;

  public Person(String name, int age, Address address)

    this.name = name;

    this.age = age;

    this.address = address;

  

  public String getName()

    return name;

  

  public int getAge()

    return age;

  

  public Address getAddress()

    return address;

  

  @Override

  public Object clone() throws CloneNotSupportedException {

    Person cloned = (Person) super.clone();

    cloned.address = (Address) address.clone();

    return cloned;

  }

}

public class Address implements Cloneable {

  private String city;

  private String street;

  public Address(String city, String street)

    this.city = city;

    this.street = street;

  

  public String getCity()

    return city;

  

  public String getStreet()

    return street;

  

  @Override

  public Object clone() throws CloneNotSupportedException {

    return super.clone();

  }

}

public class Main {

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

    Address address = new Address("Beijing", "Haidian");

    Person person1 = new Person("Tom", 18, address);

    Person person2 = (Person) person1.clone();

    System.out.println(person1 == person2); // false

    System.out.println(person1.getName() == person2.getName()); // true,String类型为不可变类型,存储于字符常量池中

    System.out.println(person1.getAge() == person2.getAge()); // true,int为基本数据类型

    System.out.println(person1.getAddress() == person2.getAddress()); // false,Address对象在clone()方法中被拷贝

  }

}

在上面的代码中,我们创建了一个Person类,并在类中重写了clone()方法来实现对象拷贝。由于Person类中有一个Address对象,我们还需要在Address类中重写clone()方法。

在main()方法中,我们创建了一个Person对象person1,然后使用clone()方法将其拷贝到person2中。接着,我们比较了person1和person2的引用地址以及个别属性是否相等。其中,地址对象为新创建的对象,而其他属性则引用到了相同的实例。

需要注意的是,要实现对象拷贝,被拷贝的对象和拷贝对象都需要实现Cloneable接口,并重写clone()方法。

2. 使用序列化

使用序列化的方式,可以将对象转化为字节流并写入文件或网络中。当需要将对象从文件或网络中读取并还原成对象时,可以用反序列化的方式来实现。

下面是一个示例:


public class Person implements Serializable {

  private String name;

  private int age;

  private Address address;

  public Person(String name, int age, Address address)

    this.name = name;

    this.age = age;

    this.address = address;

  

  public String getName()

    return name;

  

  public int getAge()

    return age;

  

  public Address getAddress()

    return address;

  

}

public class Address implements Serializable {

  private String city;

  private String street;

  public Address(String city, String street)

    this.city = city;

    this.street = street;

  

  public String getCity()

    return city;

  

  public String getStreet()

    return street;

  

}

public class Main {

  public static void main(String[] args) throws IOException, ClassNotFoundException {

    Address address = new Address("Beijing", "Haidian");

    Person person1 = new Person("Tom", 18, address);

    // 序列化

    ByteArrayOutputStream byteOut = new ByteArrayOutputStream();

    ObjectOutputStream objOut = new ObjectOutputStream(byteOut);

    objOut.writeObject(person1);

    // 反序列化

    ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());

    ObjectInputStream objIn = new ObjectInputStream(byteIn);

    Person person2 = (Person) objIn.readObject();

    System.out.println(person1 == person2); // false

    System.out.println(person1.getName() == person2.getName()); // true,String类型为不可变类型,存储于字符常量池中

    System.out.println(person1.getAge() == person2.getAge()); // true,int为基本数据类型

    System.out.println(person1.getAddress() == person2.getAddress()); // false,Address对象被序列化后又被反序列化成了新的对象

  }

}

在上面的代码中,我们创建了一个Person类和一个Address类,并使它们都实现了Serializable接口。然后,我们在main()方法中实例化了一个Person对象,将其序列化后再反序列化生成一个新的Person对象person2,并比较了其内部属性是否相等。

需要注意,使用序列化方式的对象必须实现Serializable接口。同时,序列化和反序列化过程中需要使用ObjectOutputStream和ObjectInputStream类的实例来完成。

三个

  
  

评论区

{{item['qq_nickname']}}
()
回复
回复