JAVA深拷贝和浅拷贝的实现

    xiaoxiao2022-07-04  159

    Java深拷贝和浅拷贝的理解

    Java中的对象拷贝主要分为:浅拷贝(Shallow Copy)、深拷贝(Deep Copy)。 Java中的数据类型分为基本数据类型和引用数据类型。对于这两种数据类型,在进行赋值操作、用作方法参数或返回值时,会有值传递和引用(地址)传递的差别。

    浅拷贝

    1.通过构造方法实现浅拷贝

    package copy; /** * @author zhouxuan * @since 2019/5/22 */ public class ShallowCopy { public static void main(String[] agrs){ Stock stock = new Stock(100); Car p1 = new Car("Audi",stock); Car p2 = new Car(p1); System.out.println("修改前:"); System.out.println("p1:" + p1.toString()); System.out.println("p2:" + p2.toString()); //修改基本数据类型数据 p1.setBrand("Porches"); //修改引用类型数据 stock.setStock(999); System.out.println("修改后:"); System.out.println("p1:" + p1.toString()); System.out.println("p2:" + p2.toString()); } } class Car { private String brand; private Stock stock; public Car(String brand, Stock stock) { this.brand = brand; this.stock = stock; } public Car(Car car){ this.brand = car.brand; this.stock = car.stock; } public String getBrand() { return brand; } public void setBrand(String brand) { this.brand = brand; } public Stock getStock() { return stock; } public void setStock(Stock stock) { this.stock = stock; } @Override public String toString() { return "brand='" + brand + '\'' + ", stock=" + stock; } } class Stock{ private int stock; public Stock(int stock) { this.stock = stock; } public int getStock() { return stock; } public void setStock(int stock) { this.stock = stock; } @Override public String toString() { return ""+this.getStock(); } }

    运行结果如下:

    修改前: p1:brand='Audi', stock=100 p2:brand='Audi', stock=100 修改后: p1:brand='Porches', stock=999 p2:brand='Audi', stock=999

    从运行结果我们可以看出: 对于基本数据类型(字符串类型)的修改,p1的修改并不会影响p2。 对于引用类型的修改,p2的修改导致了p1中的数据也随之变化。

    2.通过重写clone()接口实现浅拷贝 所有类的都有一个Obeject根类,Obeject中提供了clone()方法: protected native Object clone() throws CloneNotSupportedException; 但我们不能直接调用clone()方法,需要实现Cloneable接口,否则会抛出CloneNotSupportedException异常。我们可以在类中重写clone()方法,实现浅拷贝

    public class ShallowCopyClone { public static void main(String[] agrs) { Price price = new Price(100); Computer p1 = new Computer(price, 999); Computer p2 = (Computer) p1.copy(); System.out.println("修改前"); System.out.println(p1.toString()); System.out.println(p2.toString()); p1.setStock(20); price.setPrice(123); System.out.println("修改后"); System.out.println(p1.toString()); System.out.println(p2.toString()); } } class Computer implements Cloneable{ private Price price; private int stock; public Computer(Price price, int stock) { this.price = price; this.stock = stock; } public Computer(Computer computer) { this.price = computer.price; this.stock = computer.stock; } public Price getPrice() { return price; } public void setPrice(Price price) { this.price = price; } public int getStock() { return stock; } public void setStock(int stock) { this.stock = stock; } @Override public String toString() { return "price=" + price.getPrice() + ", stock='" + stock ; } public Object copy() { Object obj = null; try { obj = super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return obj; } } class Price{ private int price; public Price(int price) { this.price = price; } public int getPrice() { return price; } public void setPrice(int price) { this.price = price; }

    运行结果:

    修改前: price=100, stock='999 price=100, stock='999 修改后: price=123, stock='20 price=123, stock='999

    深拷贝

    深拷贝将对所有对象开辟新的内存空间而不是引用。 如A对象包含B对象,则会对A、B对象开辟新的内存空间实现拷贝。此时修改拷贝前后对象不会互相造成影响。 1.通过序列化和反序列化实现深拷贝 需要拷贝的类实现Serializable接口,否则会抛出NotSerializableException异常。

    public class DeepCopy { public static void main(String[] args) throws IOException, ClassNotFoundException { Category category = new Category(1); Watch p1 = new Watch("high", category); ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos); //将p1序列化 oos.writeObject(p1); oos.flush(); //反序列化 ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray())); Watch p2 = (Watch) ois.readObject(); System.out.println("修改前:"); System.out.println(p1.toString()); System.out.println(p2.toString()); System.out.println("修改后:"); p1.setLevel("low"); category.setCategory(2); System.out.println(p1.toString()); System.out.println(p2.toString()); } } class Watch implements Serializable{ private String level; private Category category; public Watch(Watch watch) { this.level = watch.level; this.category = watch.category; } public Watch(String level, Category category) { this.level = level; this.category = category; } public String getLevel() { return level; } public void setLevel(String level) { this.level = level; } public Category getCategory() { return category; } public void setCategory(Category category) { this.category = category; } @Override public String toString() { return "Watch{" + "level='" + level + '\'' + ", category=" + category + '}'; } } class Category implements Serializable{ private int category; public Category(int category) { this.category = category; } public int getCategory() { return category; } public void setCategory(int category) { this.category = category; } @Override public String toString() { return "Category{" + "category=" + category + '}'; } }

    运行结果:

    修改前: Watch{level='high', category=Category{category=1}} Watch{level='high', category=Category{category=1}} 修改后: Watch{level='low', category=Category{category=2}} Watch{level='high', category=Category{category=1}}
    最新回复(0)