java中的拷贝

这里说的拷贝主要是针对引用类型,而对于基本数据类型,拷贝就是直接把值给另一个对象

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序列化

posted @   ning12  阅读(23)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示