深拷贝和浅拷贝最根本的区别在于是否真正获取一个对象的复制实体,而不是引用。
假设B复制了A,修改A的时候,看B是否发生变化:
如果B跟着也变了
,说明是浅拷贝,拿人手短!(修改堆内存中的同一个值)
如果B没有改变
,说明是深拷贝,自食其力!(修改堆内存中的不同的值)
浅复制:仅仅是指向被复制的内存地址,如果原地址发生改变,那么浅复制出来的对象也会相应的改变。
深复制:在计算机中开辟一块新的内存地址
用于存放复制的对象。
@Data
public class HeroSkill {
String skillName;
}
@Data
public class Hero {
private String heroName;
private String heroAge;
private HeroSkill heroSkill;
}
public class HeroApplication {
public static void main(String[] args) {
//-- 新建对象
HeroSkill skill = new HeroSkill("打虎");
Hero hero = new Hero("武松", 19, skill);
System.out.println(hero);
System.out.println("========= 开始复制 ===========");
//-- 拷贝对象
Hero hero1 = new Hero();
hero1.setHeroName(hero.getHeroName());
hero1.setHeroAge(hero.getHeroAge());
hero1.setHeroSkill(hero.getHeroSkill());
System.out.println(hero);
System.out.println(hero1);
System.out.println("========= 开始修改 ===========");
//-- 修改对象
hero1.setHeroName("鲁智深");
hero1.getHeroSkill().setSkillName("拔树");
System.out.println(hero);
System.out.println(hero1);
}
}
浅拷贝可以通过Cloneable接口来实现。
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Hero implements Cloneable {
private String heroName;
private Integer heroAge;
private HeroSkill heroSkill;
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
测试代码如下:
public class HeroCloneApplication {
public static void main(String[] args) throws CloneNotSupportedException {
//-- 新建对象
HeroSkill skill = new HeroSkill("打虎");
Hero hero = new Hero("武松", 19, skill);
System.out.println(hero);
System.out.println("========= 开始复制 ===========");
Hero hero1 = (Hero)hero.clone();
System.out.println(hero);
System.out.println(hero1);
System.out.println("========= 开始修改 ===========");
//-- 修改对象
hero1.setHeroName("鲁智深");
hero1.getHeroSkill().setSkillName("拔树");
System.out.println(hero);
System.out.println(hero1);
}
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public class HeroSkill implements Cloneable{
String skillName;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
class Heros implements Cloneable {
private String heroName;
private String heroAge;
private HeroSkills heroSkill;
public Heros(String heroName, String heroAge, HeroSkills heroSkill) {
this.heroName = heroName;
this.heroAge = heroAge;
this.heroSkill = heroSkill;
}
public Heros() {
}
//... get and set
@Override
public String toString() {
return "name="+heroName+",age="+heroAge+",skill="+heroSkill.getSkillName();
}
@Override
public Object clone() throws CloneNotSupportedException {
Heros heros = (Heros)super.clone();
heros.setHeroSkill((HeroSkills)heroSkill.clone());
return heros;
}
}
public class HeroDeepCloneApplication {
public static void main(String[] args) throws CloneNotSupportedException {
//-- 新建对象
HeroSkill skill = new HeroSkill("打虎");
Hero hero = new Hero("武松", 19, skill);
System.out.println(hero);
System.out.println("========= 开始复制 ===========");
Hero hero1 = (Hero)hero.clone();
System.out.println(hero);
System.out.println(hero1);
System.out.println("========= 开始修改 ===========");
//-- 修改对象
hero1.setHeroName("鲁智深");
hero1.getHeroSkill().setSkillName("拔树");
System.out.println(hero);
System.out.println(hero1);
}
}