结合JVM解读浅拷贝和深拷贝

您所在的位置:网站首页 java深拷贝和浅拷贝说法错误的是 结合JVM解读浅拷贝和深拷贝

结合JVM解读浅拷贝和深拷贝

2024-06-24 17:37| 来源: 网络整理| 查看: 265

java.lang.Cloneable和java.io.Serializable一样属于标记型接口,没有定义任何方法和属性。 在这里插入图片描述

一个类想要使用克隆方法 重写clone()方法,因为Object的clone()的修饰符是protected; @HotSpotIntrinsicCandidate protected native Object clone() throws CloneNotSupportedException; 实现Cloneable接口,否则会抛出CloneNotSupportedException异常。 在这里插入图片描述 克隆类型 浅拷贝,拷贝对象时仅拷贝对象本身和对象中的基本变量,而不拷贝对象包含的引用指向的对象深拷贝,不仅拷贝对象本身,而且拷贝对象包含的引用指向的所有对象 举个栗子

这里使用User、Phone举例。 测试浅拷贝、深拷贝所用的Main方法如下:

public class CloneTest { public static void main(String[] args) throws CloneNotSupportedException { // 预置数据 Phone phone1 = new Phone(); String number = "11111111111"; phone1.setPhoneNum(number); String name = new String("dkangel"); int age = 24; User user1 = new User(name, age, phone1); User user2 = (User) user1.clone(); System.out.println("对象是否相等:" + (user1 == user2)); System.out.println("类的类型是否相等:" + (user1.getClass() == user2.getClass())); System.out.println("age属性是否相等:" + (user1.getAge() == user2.getAge())); System.out.println("name属性是否相等:" + (user1.getName() == user2.getName())); System.out.println("对象的对象属性Phone是否相等:" + (user1.getPhone() == user2.getPhone())); } } 浅拷贝

只拷贝对象本身,Phone不需要实现Cloneable接口和重写clone()方法。

public class Phone { private String phoneNum; public String getPhoneNum() { return phoneNum; } public void setPhoneNum(String phoneNum) { this.phoneNum = phoneNum; } } public class User implements Cloneable { private String name; private int age; private Phone phone; public User(String name, int age, Phone phone) { this.name = name; this.age = age; this.phone = phone; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Phone getPhone() { return phone; } public void setPhone(Phone phone) { this.phone = phone; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } }

user2是user1的浅拷贝,只拷贝user1对象本身,未拷贝成员变量phone,所以两者phone对象相等 在这里插入图片描述

深拷贝

不仅拷贝对象本身,而且拷贝对象所指向的所有对象,所以Phone类也要支持clone。

public class Phone implements Cloneable{ private String phoneNum; public String getPhoneNum() { return phoneNum; } public void setPhoneNum(String phoneNum) { this.phoneNum = phoneNum; } @Override public Object clone() throws CloneNotSupportedException { return super.clone(); } }

User.java 这里只粘贴clone()方法,其他和浅克隆保持一致

public class User implements Cloneable { @Override protected Object clone() throws CloneNotSupportedException { User user = (User) super.clone(); user.phone = (Phone) user.getPhone().clone(); return user; } }

user2是user1的深拷贝,拷贝user1本身的同时也拷贝一份phone1对象,两者phone对象不再相等 在这里插入图片描述

结合JVM内存分区理解下浅拷贝和深拷贝

在这里插入图片描述 看上图可知,JVM内存分为五个部分堆、方法区、程序计数器、虚拟机栈、本地方法栈,在这里我们只关注

存放对象的堆存放基本数据类型和对象引用的虚拟机栈存放类基本信息的方法区 浅拷贝解读

模式下从上到下解读CloneTest的main方法,得出如下对象在JVM中的分布图。 这里采用句柄模式访问对象(还有直接地址模式),简单解读下

new出来的对象phone1存入堆的实例池里;字符串number由于使用引号创建,所以存到堆中的字符串常量池;字符串name使用new创建,所以存入String实例池;age属于基本数据类型所以存入虚拟机栈;user1在堆中分配内存,通过clone对象user1本身的数据创建对象user2,user2的属性name/age/phone都与user1共用。

在这里插入图片描述

深拷贝解读

通过深拷贝创建的user2,不再与user1对象共用phone属性。深拷贝不仅拷贝了user1本身,也拷贝了user1的phone1对象。

这里只粘贴了与浅拷贝不同的地方,user2的phone属性由指向phone1改为指向phone2 在这里插入图片描述

如若有错误还望不吝指出,peace



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3