温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
  • 忘记密码?
登录注册×
获取短信验证码
其他方式登录
点击 登录注册 即表示同意 《亿速云用户服务条款》
  • 服务器
  • 数据库
  • 开发技术
  • 网络安全
  • 互联网科技
登 录 注册有礼
最新更新 网站标签 地图导航
产品
  • 首页 > 
  • 教程 > 
  • 开发技术 > 
  • Java中深拷贝,浅拷贝与引用拷贝的区别是什么

Java中深拷贝,浅拷贝与引用拷贝的区别是什么

发布时间:2022-08-23 14:00:14 来源:亿速云 阅读:123 作者:iii 栏目: 开发技术

这篇文章主要介绍了Java中深拷贝,浅拷贝与引用拷贝的区别是什么的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Java中深拷贝,浅拷贝与引用拷贝的区别是什么文章都会有所收获,下面我们一起来看看吧。

引用拷贝

引用拷贝: 引用拷贝不会在堆上创建一个新的对象,只 会在栈上生成一个新的引用地址,最终指向依然是堆上的同一个对象

//实体类
public class Person{
    public String name;//姓名
    public int height;//身高
    public StringBuilder something;

    public String getName() {
        return name;
    }

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

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    public StringBuilder getSomething() {
        return something;
    }

    public void setSomething(StringBuilder something) {
        this.something = something;
    }

    public Person(String name, int height, StringBuilder something) {
        this.name = name;
        this.height = height;
        this.something = something;
    }

}

//测试类
public class copyTest {
    public static void main(String[] args) {
        Person p1 = new Person("小张", 180, new StringBuilder("今天天气很好"));
        Person p2 = p1;

        System.out.println("对象是否相等:"+ (p1 == p2));
        System.out.println("p1 属性值=" + p1.getName()+ ","+ p1.getHeight() + ","+ p1.getSomething());
        System.out.println("p2 属性值=" + p2.getName()+ ","+ p2.getHeight() + ","+ p2.getSomething());


        // change
        p1.name="小王";
        p1.height = 200;
        p1.something.append(",适合出去玩");
        System.out.println("...after p1 change....");

        System.out.println("p1 属性值=" + p1.getName()+ ","+ p1.getHeight() + ","+ p1.getSomething());
        System.out.println("p2 属性值=" + p2.getName()+ ","+ p2.getHeight() + ","+ p2.getSomething());

    }
}

结果:

对象是否相等:true
p1 属性值=小张,180,今天天气很好
p2 属性值=小张,180,今天天气很好
...after p1 change....
p1 属性值=小王,200,今天天气很好,适合出去玩
p2 属性值=小王,200,今天天气很好,适合出去玩

before change:

Java中深拷贝,浅拷贝与引用拷贝的区别是什么

after change:

Java中深拷贝,浅拷贝与引用拷贝的区别是什么

我们可以看出 由于2个引用p1,p2 都是指向堆中同一个对象,所以2个对象是相等的,修改了对象p1,会影响到对象p2
需要注意的

  • name属性,虽然她是引用类型,但她同时也是String类型,不可变,对其修改,JVM会默认在堆上创建新的内存空间,再重新赋值

  • int weight=180; 是成员变量,存放在堆中,不是所有的基本类型变量 都存放在JVM栈中

注意与这篇文章得区分开来, int num1 = 10;是基本类型的局部变量,存放在栈中

浅拷贝

浅拷贝 :浅拷贝会在堆上创建一个新的对象,新对象和原对象不等,但是新对象的属性和老对象相同

其中:

  • 如果属性是基本类型(int,double,long,boolean等),拷贝的就是基本类型的值。

  • 如果属性是引用类型(除了基本类型都是引用类型),拷贝的就是引⽤数据类型变量的地址值,⽽对于引⽤类型变量指向的堆中的对象不会拷贝。

如何实现浅拷贝呢?也很简单,就是在需要拷贝的类上实现Cloneable接口并重写其clone()方法

@Override protected Object clone() throws CloneNotSupportedException {   
    return super.clone(); 
}

在使用的时候直接调用类的clone()方法即可

//实体类 继承Cloneable
public class Person implements Cloneable{
    public String name;//姓名
    public int height;//身高
    public StringBuilder something;

    public String getName() {
        return name;
    }

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

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    public StringBuilder getSomething() {
        return something;
    }

    public void setSomething(StringBuilder something) {
        this.something = something;
    }

    public Person(String name, int height, StringBuilder something) {
        this.name = name;
        this.height = height;
        this.something = something;
    }



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

}

//测试类
public class shallowCopyTest {

    public static void main(String[] args) throws CloneNotSupportedException {
        Person p1 = new Person("小张", 180, new StringBuilder("今天天气很好"));
        Person p2 = p1.clone();

        System.out.println("对象是否相等:"+ (p1 == p2));
        System.out.println("p1 属性值=" + p1.getName()+ ","+ p1.getHeight() + ","+ p1.getSomething());
        System.out.println("p2 属性值=" + p2.getName()+ ","+ p2.getHeight() + ","+ p2.getSomething());


        // change
        p1.setName("小王");
        p1.setHeight(200);
        p1.getSomething().append(",适合出去玩");
        System.out.println("...after p1 change....");

        System.out.println("p1 属性值=" + p1.getName()+ ","+ p1.getHeight() + ","+ p1.getSomething());
        System.out.println("p2 属性值=" + p2.getName()+ ","+ p2.getHeight() + ","+ p2.getSomething());

    }
}

结果:

对象是否相等:false
p1 属性值=小张,180,今天天气很好
p2 属性值=小张,180,今天天气很好
...after p1 change....
p1 属性值=小王,200,今天天气很好,适合出去玩
p2 属性值=小张,180,今天天气很好,适合出去玩

before change:

Java中深拷贝,浅拷贝与引用拷贝的区别是什么

after change:

Java中深拷贝,浅拷贝与引用拷贝的区别是什么

我们可以看出:

  • 当我们修改对象p1的weight属性时,由于p2的height属性 是直接复制修改前的p1的height属性,所以还是180。

  • 当我们修改对象p1的name属性 时,String name指向一个新的内存空间,但对象p2的name还是指向旧的内存空间,所以对象p2的name属性还是"小张"。

  • 由于对象p1的something属性和对象p2的something属性指向是同一个内存空间,当我们修改对象p1的something属性,会影响到对象p2的something属性,所以对象p2的something属性变为"今天天气很好,适合出去玩"。

深拷贝

深拷贝 :完全拷贝⼀个对象,在堆上创建一个新的对象,拷贝被拷贝对象的成员变量的值,同时堆中的对象也会拷贝。
需要重写clone方法

    @Override
    public Person clone() throws CloneNotSupportedException {
        //return (Person) super.clone();
        Person person = (Person) super.clone();
        person.setSomething( new StringBuilder(person.getSomething()));//单独为引用类型clone
        return person;
    }

shallowCopyTest测试类的结果:

对象是否相等:false
p1 属性值=小张,180,今天天气很好
p2 属性值=小张,180,今天天气很好
...after p1 change....
p1 属性值=小王,200,今天天气很好,适合出去玩
p2 属性值=小张,180,今天天气很好

这时候对象p1和对象p2互不干扰了

before change:

Java中深拷贝,浅拷贝与引用拷贝的区别是什么

after change:

Java中深拷贝,浅拷贝与引用拷贝的区别是什么

但这样也有个小问题,对象每有一个引用类型,我们都得重写其clone方法,这样会非常麻烦,因此我们还可以借助序列化来实现对象的深拷贝

//实体类 继承Cloneable
public class Person implements Serializable{
    public String name;//姓名
    public int height;//身高
    public StringBuilder something;

...//省略 getter setter


    public Object deepClone() throws Exception{
        // 序列化
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
    
        oos.writeObject(this);
    
        // 反序列化
        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bis);
    
        return ois.readObject();
    }

}

//测试类,这边类名笔者就不换了,在之前的基础上改改
public class shallowCopyTest {

    public static void main(String[] args) throws Exception {
        Person p1 = new Person("小张", 180, new StringBuilder("今天天气很好"));
        Person p2 = (Person)p1.deepClone();

        System.out.println("对象是否相等:"+ (p1 == p2));
        System.out.println("p1 属性值=" + p1.getName()+ ","+ p1.getHeight() + ","+ p1.getSomething());
        System.out.println("p2 属性值=" + p2.getName()+ ","+ p2.getHeight() + ","+ p2.getSomething());


        // change
        p1.setName("小王");
        p1.setHeight(200);
        p1.getSomething().append(",适合出去玩");
        System.out.println("...after p1 change....");

        System.out.println("p1 属性值=" + p1.getName()+ ","+ p1.getHeight() + ","+ p1.getSomething());
        System.out.println("p2 属性值=" + p2.getName()+ ","+ p2.getHeight() + ","+ p2.getSomething());

    }
}

这样也会得到深拷贝的结果

小结

引用拷贝: 引用拷贝不会在堆上创建一个新的对象,只 会在栈上生成一个新的引用地址,最终指向依然是堆上的同一个对象

浅拷贝 :浅拷贝会在堆上创建一个新的对象,新对象和原对象不等,但是新对象的属性和老对象相同

其中:

如果属性是基本类型(int,double,long,boolean等),拷贝的就是基本类型的值。

如果属性是引用类型(除了基本类型都是引用类型),拷贝的就是引⽤数据类型变量的地址值,⽽对于引⽤类型变量指向的堆中的对象不会拷贝。

深拷贝 :完全拷贝⼀个对象,在堆上创建一个新的对象,拷贝被拷贝对象的成员变量的值,同时堆中的对象也会拷贝。

关于“Java中深拷贝,浅拷贝与引用拷贝的区别是什么”这篇文章的内容就介绍到这里,感谢各位的阅读!相信大家对“Java中深拷贝,浅拷贝与引用拷贝的区别是什么”知识都有一定的了解,大家如果还想学习更多知识,欢迎关注亿速云行业资讯频道。

向AI问一下细节
推荐阅读:
  1. python列表--浅拷贝与深拷贝的区别
  2. 深拷贝&浅拷贝

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

java
  • 上一篇新闻:
    怎么用filebeat收集多个域名网站日志并存储到不同es索引库
  • 下一篇新闻:
    goodnotes如何使用

猜你喜欢

  • java中lambda的用法是什么
  • lambda表达式的用法是什么
  • android spinner怎么添加事件监听
  • android监听事件的方法有哪些
  • ​MariaDB的功能有哪些
  • python watchdog监控不到文件变化怎么解决
  • react hoc组件的使用方法是什么
  • Teradata数据库的特点有哪些
  • android无法访问data目录怎么解决
  • Impla如何查所有库和表名
最新资讯
  • 如何在React中集成Markdown编辑器并实现实时预览功能
  • 在React中如何实现多个API请求的串行与并行处理
  • 如何利用React Portals在模态对话框等场景中管理DOM层次结构外的组件
  • 如何在React应用中实现全局热键功能
  • 如何在React中结合使用Context API和Hooks进行状态管理以避免Redux的复杂性
  • 在React中如何使用React.lazy和Suspense进行路由级代码分割
  • 如何在React应用中优化长文本内容的显示
  • React中如何处理高阶组件的属性透传问题
  • 如何在React中实现拖放界面元素的功能
  • 如何在React项目中配置和使用TypeScript以增强代码的可维护性和稳定性
相关推荐
  • JavaScript深拷贝与浅拷贝
  • Java中的浅拷贝与深拷贝
  • javascript中深拷贝与浅拷贝的区别是什么
  • python中深拷贝与浅拷贝的区别是什么
  • javaScript中浅拷贝与深拷贝的区别是什么
  • JS中的深拷贝与浅拷贝是什么
  • Java深拷贝与浅拷贝的区别是什么
  • JS基本和引用数据深拷贝及浅拷贝的区别
  • Java中的深拷贝与浅拷贝的意思
  • JavaScript深拷贝与浅拷贝是什么

相关标签

java8 java学习路线 java线程 javascrip 初学java java环境 java内存模型 java web java后端 java接口 javaw.exe java包 java集合 javascript函数 java运算符 java文件 java版本 java锁 javamailsender java云虚拟主机
AI

深圳SEO优化公司驻马店建网站诸城外贸网站建设公司西安百度网站优化推荐济源企业网站制作公司朔州网站设计模板价格新余百度竞价价格西乡关键词排名包年推广价格南澳企业网站改版价格娄底至尊标王价格郑州网站搜索优化公司林芝建站报价眉山营销型网站建设公司北海外贸网站设计报价福州企业网站建设推荐忻州关键词排名哪家好德宏网络广告推广哪家好西宁网站优化软件价格垦利seo网站优化和田建站推荐丽水网络推广报价防城港推广网站推荐龙华seo哪家好吕梁模板网站建设临夏SEO按天扣费公司许昌营销型网站建设多少钱濮阳百度seo推荐襄阳设计网站多少钱鞍山百度关键词包年推广推荐那曲模板网站建设多少钱遂宁网站设计模板歼20紧急升空逼退外机英媒称团队夜以继日筹划王妃复出草木蔓发 春山在望成都发生巨响 当地回应60岁老人炒菠菜未焯水致肾病恶化男子涉嫌走私被判11年却一天牢没坐劳斯莱斯右转逼停直行车网传落水者说“没让你救”系谣言广东通报13岁男孩性侵女童不予立案贵州小伙回应在美国卖三蹦子火了淀粉肠小王子日销售额涨超10倍有个姐真把千机伞做出来了近3万元金手镯仅含足金十克呼北高速交通事故已致14人死亡杨洋拄拐现身医院国产伟哥去年销售近13亿男子给前妻转账 现任妻子起诉要回新基金只募集到26元还是员工自购男孩疑遭霸凌 家长讨说法被踢出群充个话费竟沦为间接洗钱工具新的一天从800个哈欠开始单亲妈妈陷入热恋 14岁儿子报警#春分立蛋大挑战#中国投资客涌入日本东京买房两大学生合买彩票中奖一人不认账新加坡主帅:唯一目标击败中国队月嫂回应掌掴婴儿是在赶虫子19岁小伙救下5人后溺亡 多方发声清明节放假3天调休1天张家界的山上“长”满了韩国人?开封王婆为何火了主播靠辱骂母亲走红被批捕封号代拍被何赛飞拿着魔杖追着打阿根廷将发行1万与2万面值的纸币库克现身上海为江西彩礼“减负”的“试婚人”因自嘲式简历走红的教授更新简介殡仪馆花卉高于市场价3倍还重复用网友称在豆瓣酱里吃出老鼠头315晚会后胖东来又人满为患了网友建议重庆地铁不准乘客携带菜筐特朗普谈“凯特王妃P图照”罗斯否认插足凯特王妃婚姻青海通报栏杆断裂小学生跌落住进ICU恒大被罚41.75亿到底怎么缴湖南一县政协主席疑涉刑案被控制茶百道就改标签日期致歉王树国3次鞠躬告别西交大师生张立群任西安交通大学校长杨倩无缘巴黎奥运

深圳SEO优化公司 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化