java中的拷贝

33 阅读3分钟

1.浅拷贝(只拷贝原对象的地址)

  1. 原对象的值发生变化,拷贝对象的值也会随之发生变化,因为原对象和拷贝对象是同一块空间
  2.  // 实体类
     public class User {
         private String name = "张三";
         private String password = "123456";
     ​
         public String getName() {
             return name;
         }
     ​
         public void setName(String name) {
             this.name = name;
         }
     ​
         public String getPassword() {
             return password;
         }
     ​
         public void setPassword(String password) {
             this.password = password;
         }
     ​
         @Override
         public String toString() {
             return "User{" +
                     "name='" + name + ''' +
                     ", password='" + password + ''' +
                     '}';
         }
     }
     ​
     // 测试类
     class Test {
         public static void main(String[] args) {
             // 浅拷贝
             User user1 = new User();
             System.out.println(user1);
             User user2 = user1;
             System.out.println(user2);
             System.out.println("密码改变前:");
             System.out.println(user1.getPassword());
             System.out.println(user2.getPassword());
             user1.setPassword("123");
             System.out.println("密码改变后:");
             System.out.println(user1.getPassword());
             System.out.println(user2.getPassword());
         }
     }
     ​
    

2.深拷贝(拷贝原对象的所有值)

  1. 原对象的值发生变化,拷贝对象的值不发生变化,因为原对象与拷贝对象是两份不同的空间

  2.  // 测试类
     class Test {
         public static void main(String[] args) {
             // 深拷贝
             User user1 = new User();
             user1.setName("李四");
             user1.setPassword("666");
     ​
             User user2 = new User();
             user2.setName(user1.getName());
             user2.setPassword(user1.getPassword());
             System.out.println(user1);
             System.out.println(user2);
             System.out.println("密码改变前:");
             System.out.println(user1.getPassword());
             System.out.println(user2.getPassword());
             user1.setPassword("123");
             System.out.println("密码改变后:");
             System.out.println(user1.getPassword());
             System.out.println(user2.getPassword());
     ​
         }
     }
    

    上面的代码就是构造器方式进行深拷贝,发现,是把user1中的每个属性都赋值给user2的属性,这种方法固然可以,但是太过于繁琐

  3. 深拷贝的方式

    1. 构造器方式(对象少量时可以使用此方法;要拷贝大量对象时,因为要不停的new对象,开销比较大,所以不推荐)

    2. 重写clone方法方式

      1. 实现Cloneable接口,目的是为了告诉jvm本类允许被拷贝

      2. 重写Object中的clone方法,修改clone方法的访问修饰符,由protected改成public

      3.  public class User implements Cloneable {
             private String name = "张三";
             private String password = "123456";
         ​
             public String getName() {
                 return name;
             }
         ​
             public void setName(String name) {
                 this.name = name;
             }
         ​
             public String getPassword() {
                 return password;
             }
         ​
             public void setPassword(String password) {
                 this.password = password;
             }
         ​
             @Override
             public String toString() {
                 return "User{" +
                         "name='" + name + ''' +
                         ", password='" + password + ''' +
                         '}';
             }
         ​
             @Override
             public User clone() throws CloneNotSupportedException {
                 return (User) super.clone();
             }
         }
        
      4.  public class Test {
             public static void main(String[] args) throws CloneNotSupportedException {
                 // 浅拷贝
                 // clone方法实现
                 User user1 = new User();
                 user1.setName("李四");
                 User user2 = user1.clone();
         ​
                 System.out.println("密码改变前:");
                 System.out.println(user1);
                 System.out.println(user2);
                 user1.setPassword("123");
                 System.out.println("密码改变后:");
                 System.out.println(user1);
                 System.out.println(user2);
         ​
             }
         }
        

        但是默认的clone只能拷贝一层的对象,对于超过一层的对象,只能进行浅拷贝,例如下面的代码,是两层的拷贝,在第二层的person类型的拷贝中,只是进行了浅拷贝

      5.  class Person {
             private String name;
         ​
             public String getName() {
                 return name;
             }
         ​
             public void setName(String name) {
                 this.name = name;
             }
         ​
             @Override
             public String toString() {
                 return "Person{" +
                         "name='" + name + ''' +
                         '}';
             }
         }
         ​
         class User implements Cloneable {
             private String name = "张三";
             private String password = "123456";
             private Person person = new Person();
         ​
             public String getName() {
                 return name;
             }
         ​
             public void changePersonName(String name) {
                 person.setName(name);
             }
         ​
             public String getPersonName() {
                 return person.getName();
             }
         ​
             public void setName(String name) {
                 this.name = name;
             }
         ​
             public String getPassword() {
                 return password;
             }
         ​
             public void setPassword(String password) {
                 this.password = password;
             }
         ​
             @Override
             public String toString() {
                 return "User{" +
                         "name='" + name + ''' +
                         ", password='" + password + ''' +
                         ", person=" + person +
                         '}';
             }
         ​
             @Override
             public User clone() throws CloneNotSupportedException {
                 return (User) super.clone();
             }
         }
        
      6.  public class Test {
             public static void main(String[] args) throws CloneNotSupportedException {
                 User user1 = new User();
                 User user2 = user1.clone();
                 System.out.println("修改内部引用类型属性前:");
                 System.out.println(user1);
                 System.out.println(user2);
                 user1.changePersonName("wangwu");
                 user1.setName("zhangsan");
                 System.out.println("修改内部引用类型属性后:");
                 System.out.println(user1);
                 System.out.println(user2);
         ​
             }
         }
        
    3. Apache Common Lang序列化

    4. Gson序列化

    5. JackSon序列化