首页 > 编程语言 >java中的拷贝

java中的拷贝

时间:2024-05-16 15:07:40浏览次数:20  
标签:java String System println 拷贝 out public name

目录

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

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

标签:java,String,System,println,拷贝,out,public,name
From: https://www.cnblogs.com/ning23/p/18195996

相关文章

  • LLM-通义千问:掌握的Java知识过于零散,怎么系统地串一串
    要系统地整理和深化你的Java知识,可以遵循以下几个步骤和策略:1.回顾基础语言基础:从Java的基本语法开始,包括变量声明、数据类型、运算符、控制结构(if-else,for,while等)、数组和方法定义。面向对象编程:深入理解类与对象、继承、封装、多态这些核心概念,并实践如何设计良好的类......
  • java下载zip文件
    一、使用工具*java.utils下的ZipOutputStream*java.net的http请求工具HttpURLConnection二、zip下载1.通过浏览器以附件的形式下载到客户端思路:response的write方法要写出一个byte[],所以我们需要从ZipStreamOutputStream中获取到byte[]。在java中......
  • JavaSE入门学习
    Java入门学习目录Java入门学习Java特征和优势Java三大版本开发环境搭建JDK下载及安装配置环境变量HelloWorld及简单语法规则使用IDE开发1.创建一个Java项目(IDEA)2.在该项目src目录下new一个class文件3.编辑代码4.运行代码Java特征和优势简单性面向对象可移植性高性能......
  • 在Linux中,如何进行Java应用性能调优?
    在Linux环境中进行Java应用程序的性能调优是一个多步骤的过程,涉及到监控、分析和调整多个层面的配置。以下是进行Java应用性能调优的一些关键步骤和策略:1.监控和分析工具的使用JVM监控工具:利用jstat,jmap,jstack,和jconsole等JDK自带的工具,以及更高级的工具如VisualVM、JP......
  • JavaScript object array sort by string bug All In One
    JavaScriptobjectarraysortbystringbugAllInOnebug//purestringsarray,sortOK✅letarr=["banana","strawberry","apple"];JSON.stringify(arr.sort());//'["apple","banana","strawbe......
  • JAVA版的代码生成器gen
    自己安装方式dockerpullregistry.cn-hangzhou.aliyuncs.com/tanghc/gen:latest 下载完毕后,执行 dockerrun--namegen--restart=always\-p6969:6969\-eJAVA_OPTS="-server-Xms64m-Xmx64m-DLOCAL_DB=/opt/gen/gen.db"\-v/opt/gen/:/opt/gen/\......
  • Java面试题:让依赖注入变得简单,面对@Autowired和@Resource,该如何选择?
    @Autowired和@Resource都是JavaSpring框架中的注解,用于实现依赖注入(DI)和控制反转(IoC)。它们的区别主要在以下三个方面:源头不同 @Autowired是Spring自带的注解,而@Resource是JSR250规范中定义的注解。因此,在使用Spring框架的时候,通常建议使用@Autowired注解。  查找顺序......
  • Java响应式编程
    提纲1、响应式编程ReactiveProgramming2、ReactiveStreams3、Reactor和RxJava1、响应式编程ReactiveProgramming为了解决异步编程中出现的各种问题,程序员们提出了各种的方法和手段去解决这些问题,这些方法和手段就被称为ReactiveProgramming。ReactiveProgramming是一......
  • Java Solon v2.7.6 发布
    JavaSolon是什么框架?Java“新的”应用开发框架。开放原子开源基金会,孵化项目。从零开始构建(非java-ee架构),有灵活的接口规范与开放生态。追求:更快、更小、更简单提倡:克制、简洁、高效、开放、生态有什么特点?更高的计算性价比:并发高2~3倍;内存省50%更快的开发效......
  • Java-SSM-Day03 SpringFramework实战指南(二)
    4.2.2实验二:组件(Bean)依赖注入配置(DI)1.目标:通过配置文件,实现IoC容器中Bean之间的引用(依赖注入的DI配置)主要涉及注入场景:基于构造函数的依赖注入和基于Setter的依赖注入。3.基于构造函数的依赖注入(单个构造参数)基于构造函数的DI是通过容器调用具有多个参数的构......