Java 应用当中将一个对象的值给到一个新的对象可以通过直接赋值和拷贝的方式进行,但两种方式我们应该清除他们之间的区别;
直接赋值(引用赋值)
定义一个对象
public class User {
private String name;
private Integer age;
private String sex;
}
给新对象赋值并修改新对象:
public static void main(String[] args){
User user1 = new User();
user1.setName("张三");
user1.setAge(20);
user1.setSex("男");
//引用赋值
User user2 = new User();
user2 = user1;
user2.setName("李四");
user2.setAge(22);
System.out.println("user1:"+user1);
System.out.println("user2:"+user2);
}
结论:
在jvm里面对象的存储在堆和栈里面,其中
栈:存放对象的基本变量和对象的引用
栈:存放new出来的实例数据
对象的直接赋值是将user1的引用地址赋值给了user2,当user2修改实例数据的时候是修改堆当中的数据,所以当user2修改完后我们再查看user1的数据时是被修改后的数据。
对象拷贝
对象拷贝都是在堆内存当中重新分配一块内存并将数据赋值到新的对象,但是由于一个对象可能存在对于其他对象的引用,针对这样的情况,将拷贝又分为深拷贝和浅拷贝;
浅拷贝:当一个对象引用别的对象时,对基本数据类型进行值传递,对引用数据类型进行引用传递般的拷贝
深拷贝:对基本数据类型进行值传递,对引用数据类型,创建一个新的对象,并复制其内容
举个例子:
1.一个对象不包含对别的对象的引用,使用浅拷贝:
//拷贝需要实现CloneAble接口,并重写clone方法
public class User implements Cloneable {
private String name;
private Integer age;
private String sex;
@Override
public Object clone(){
try {
return super.clone();
}catch (CloneNotSupportedException ignore){
}
return null;
}
}
实现浅拷贝并修改其值:
public static void main(String[] args){
User user1 = new User();
user1.setName("张三");
user1.setAge(20);
user1.setSex("男");
//浅拷贝
User user2 = (User)user1.clone();
user2.setName("李四");
user2.setAge(22);
System.out.println("user1:"+user1);
System.out.println("user2:"+user2);
}
结论: 对象的基本数据类型,浅拷贝修改user2对象值,并没有修改user1的值
2,一个对象包含了对别的对象的引用,使用浅拷贝
public class Person {
private String person;
}
public class User implements Cloneable {
private String name;
private Integer age;
private String sex;
private Person person;
@Override
public Object clone(){
try {
return super.clone();
}catch (CloneNotSupportedException ignore){
}
return null;
}
}
实现浅拷贝并修改其值:
public static void main(String[] args){
User user1 = new User();
user1.setName("张三");
user1.setAge(20);
user1.setSex("男");
Person person = new Person();
person.setPerson("morning!");
user1.setPerson(person);
//浅拷贝
User user2 = (User)user1.clone();
user2.setName("李四");
user2.setAge(22);
//修改引用对象的值,还是会修改到user1
user2.getPerson().setPerson("afternoon!");
System.out.println("user1:"+user1);
System.out.println("user2:"+user2);
}
结论:对于浅拷贝来说,对象的clone方法并不会把其对象中引用的其他对象进行拷贝
对与浅拷贝来说,如果包含对别的对象的引用,在内存中结构如下:浅拷贝对象的引用还是指向原来的引用对象,并没有重新复制一份给到新的对象
3,深拷贝,将对象引用的对象也一起复制给到新的对象形成一个新的对象
实现深拷贝方式:
1.对对象进行序列化操作,在赋值给新对象的时候反序列化
2.实现clone方式
我们通过实现clone方式来实现深拷贝:
public class Person implements Cloneable{
private String person;
@Override
public Object clone(){
try {
return super.clone();
}catch (CloneNotSupportedException ignore){
}
return null;
}
}
public class User implements Cloneable {
private String name;
private Integer age;
private String sex;
private Person person;
@Override
public Object clone(){
try {
//深拷贝
User user = (User)super.clone();
user.person = (Person)this.person.clone();
return user;
}catch (CloneNotSupportedException ignore){
}
return null;
}
public static void main(String[] args){
User user1 = new User();
user1.setName("张三");
user1.setAge(20);
user1.setSex("男");
Person person = new Person();
person.setPerson("morning!");
user1.setPerson(person);
//深拷贝 对象已经实现clone方法
User user2 = (User)user1.clone();
user2.setName("李四");
user2.setAge(22);
//修改引用对象的值,不会修改到user1的引用对象的值
user2.getPerson().setPerson("afternoon!");
System.out.println("user1:"+user1);
System.out.println("user2:"+user2);
}
结论: