数据拷贝是计算机系统中常用的操作,在编程语言中也存在拷贝,这里简单描述一下程序中的拷贝操作
使用实例代码解析深拷贝和浅拷贝
商品实体类:
package com.copy;/*** 商品信息** @author lemon*/public class Commodity implements Cloneable{private String commodityName;public String getCommodityName() {return commodityName;}public void setCommodityName(String commodityName) {this.commodityName = commodityName;}@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}@Overridepublic String toString() {return "Commodity{" +"commodityName='" + commodityName + '\'' +'}';}}
订单实体类:
package com.copy;/*** 订单信息** @author lemon*/public class Order implements Cloneable{private Integer orderId;private Commodity commodity;public Integer getOrderId() {return orderId;}public void setOrderId(Integer orderId) {this.orderId = orderId;}public Commodity getCommodity() {return commodity;}public void setCommodity(Commodity commodity) {this.commodity = commodity;}@Overrideprotected Object clone() throws CloneNotSupportedException {Order order=(Order)super.clone();order.setCommodity((Commodity) commodity.clone());return order;}@Overridepublic String toString() {return "Order{" +"orderId=" + orderId +", commodity=" + commodity +'}';}}
学生实体类:
package com.copy;/*** 定义一个引用数据类型对象** @author lemon*/public class Student implements Cloneable{/*** 学生姓名*/private String name;/*** 学生年龄*/private int age;public Student() {}public Student(String name, int age) {this.name = name;this.age = age;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}@Overridepublic Object clone() throws CloneNotSupportedException {return super.clone();}}
测试代码:
package com.copy;/*** 浅拷贝示例** @author lemon*/public class DataCopy {/*** 基本数据类型-拷贝*/public void baseDataTypeCopy() {int num1 = 10;int num2 = num1;System.out.println("num1 数据值:" + num1);System.out.println("num2 数据值:" + num2);System.out.println("修改num1的数据值,查看会不会影响到num2的数据值");num1++;System.out.println("num1最新数据值:" + num1);System.out.println("num2最新数据值:" + num2);}/*** 引用数据类型-引用拷贝*/public void referenceDataTypeCopy() throws CloneNotSupportedException{//Student AStudent stuA = new Student("小A", 18);//Student BStudent stuB =stuA;System.out.println("通过copy的方式,初始化学生对象");System.out.println(stuA);System.out.println(stuB);stuA.setName("小C");stuA.setAge(28);System.out.println("修改StuA的信息,查看StuA和StuB的信息变化");System.out.println(stuA);System.out.println(stuB);}/*** 引用数据类型-浅拷贝*/public void shallowCopy() throws CloneNotSupportedException{//Student AStudent stuA = new Student("小A", 18);//Student BStudent stuB = (Student) stuA.clone();System.out.println("通过copy的方式,初始化学生对象");System.out.println(stuA);System.out.println(stuB);stuA.setName("小C");stuA.setAge(28);System.out.println("修改StuA的信息,查看StuA和StuB的信息变化");System.out.println(stuA);System.out.println(stuB);}/*** 引用数据类型-深拷贝*/public void deepCopy() throws CloneNotSupportedException{Commodity apple=new Commodity();apple.setCommodityName("Apple");Order appleOrder=new Order();appleOrder.setCommodity(apple);appleOrder.setOrderId(1);Order appleOrders=(Order)appleOrder.clone();System.out.println(appleOrder);System.out.println(appleOrders);apple.setCommodityName("HongFuShi Apple");System.out.println(appleOrder);System.out.println(appleOrders);}}class DataCopyMain{public static void main(String[]args) throws CloneNotSupportedException{DataCopy copyDemo=new DataCopy();/*** 基本数据类型拷贝** 运行结果:* num1 数据值:10* num2 数据值:10* 修改num1的数据值,查看会不会影响到num2的数据值* num1最新数据值:11* num2最新数据值:10*/copyDemo.baseDataTypeCopy();/*** 引用数据类型-引用拷贝** 运行结果:* 通过copy的方式,初始化学生对象* Student{name='小A', age=18}* Student{name='小A', age=18}* 修改StuA的信息,查看StuA和StuB的信息变化* Student{name='小C', age=28}* Student{name='小C', age=28}*/copyDemo.referenceDataTypeCopy();/*** 引用数据类型-浅拷贝** 运行结果:* 通过copy的方式,初始化学生对象* Student{name='小A', age=18}* Student{name='小A', age=18}* 修改StuA的信息,查看StuA和StuB的信息变化* Student{name='小C', age=28}* Student{name='小A', age=18}*/copyDemo.shallowCopy();/*** 引用数据类型-深拷贝** 运行结果:* Order{orderId=1, commodity=Commodity{commodityName='Apple'}}* Order{orderId=1, commodity=Commodity{commodityName='Apple'}}* Order{orderId=1, commodity=Commodity{commodityName='HongFuShi Apple'}}* Order{orderId=1, commodity=Commodity{commodityName='Apple'}}*/copyDemo.deepCopy();}}
1.baseDataTypeCopy()基本数据类型
只是简单的值引用,所以当`num1`发生改变的时候,`num2`不受影响。

引申的问题:
java中的基本数据类型在栈中是存放在什么位置的?
**涉及到的 JVM区域: 方法栈、堆内存
在方法中声明局部变量,每当程序调用方法时,系统都会为该方法建立一个方法栈,所在方法中声明的变量就放在方法栈中,当方法结束系统会释放方法栈,其对应在该方法中声明的变量随着栈的销毁而结束,这就局部变量只能在方法中有效的原因!
方法局部变量:
基本数据类型:当声明是基本类型的变量的时是放在**方法栈**中
引用数据类型:声明的变量(栈地址非数据值)是放在方法栈中,该变量所指向的对象是放在**堆内存**中
类的成员变量:
基本数据类型:当声明的是基本类型的变量,会放在**堆内存**中的
引用数据类型:其声明的变量(栈地址非数据值)放在**方法栈**,该变量所指向的对象是放在**堆内存**中
2.referenceDataTypeCopy()引用数据类型拷贝
使用 `=` 进行引用传递,两个对象的数据使用的是一个堆内存,也就是虚拟机栈是一个地址,所以修改任意一个对象的信息,另一个都会受到影响。

3.shallowCopy()引用数据类型的浅拷贝
同``referenceDataTypeCopy()`方法一样,对象中包含的引用数据类型不会在堆内存中划分空间,所以,浅拷贝的对象如果包含引用数据类型,这个引用数据和被引用对象的引用数据类型使用的一个栈地址。

4.deepCopy()引用数据类型的深拷贝
对象中包含的引用数据类型如果实现了`Cloneable`接口,并且重写了`Clone()`方法。那么,在克隆这个对象的时候,对象中的引用数据类型会在堆内存中划分空间。所以,深拷贝的对象包含的引用类型数据,发生改变不会修改被拷贝对象的数据信息。

待补充的部分
文中提到的关于`Jvm`相关的部分,因为对部分知识点不是太了解,可能会存在出入,堆栈方法区等部分需要查询一些资料,这块有瑕疵的地方,请记得留言,以后会跟进修改一下。
-End-
_
公众号:Java编码日志
