java复制的两种方式

在Java里,假如你要复制一个简单变量,很简单

int a=5;

int b=a;

这就完成了复制,不只是int,其他的基本类型(short,long,byte,boolean,char,float,double)都可以这样干。

不过你要是复制的是对象呢,

有两种方法:

1.实现 Cloneable 接口并重写 Object 类中的 clone()方法; 浅拷贝(shllow copy)

2.用对象的序列化和反序列化实现Serializable接口。这就是传说中的深拷贝(deep clone)

深拷贝的代码如下:

MyUtil类

package lovo;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class MyUtil {

	private MyUtil() {
		throw new AssertionError();
	}
	
	public static <T> T clone(T obj) throws Exception {
		ByteArrayOutputStream bout=new ByteArrayOutputStream();
		ObjectOutputStream oos=new ObjectOutputStream(bout);
		oos.writeObject(obj);
		ByteArrayInputStream bin=new ByteArrayInputStream(bout.toByteArray());
		ObjectInputStream ois=new ObjectInputStream(bin);
		return (T) ois.readObject();
		 // 说明:调用 ByteArrayInputStream 或 ByteArrayOutputStream 对象的 close 方法没有任何意义   24.    
		 // 这两个基于内存的流只要垃圾回收器清理对象就能够释放资源 
	}
}

Car类

package lovo;

import java.io.Serializable;

public class Car implements Serializable{

	
	private static final long serialVersionUID= -5713945027627603702L;   
	
	
	
	private String brand;//平拍
	private int maxSpeed;//最高时速
	
	public Car(String brand,int maxSpeed) {
		this.brand=brand;
		this.maxSpeed=maxSpeed;
	}

	public String getBrand() {
		return brand;
	}

	public void setBrand(String brand) {
		this.brand = brand;
	}

	public int getMaxSpeed() {
		return maxSpeed;
	}

	public void setMaxSpeed(int maxSpeed) {
		this.maxSpeed = maxSpeed;
	}

	@Override
	public String toString() {
		return "Car [brand=" + brand + ", maxSpeed=" + maxSpeed + "]";
	}
	
}


Person类

package lovo;

import java.io.Serializable;

public class Person implements Serializable{

	private static final long seriaVersionUID = -9102017020286042305L; 
	
	private String name;//姓名
	private int  age;//年龄
	private Car car;//座驾
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + ", car=" + car + "]";
	}
	public Person(String name, int age, Car car) {
		super();
		this.name = name;
		this.age = age;
		this.car = car;
	}
	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 Car getCar() {
		return car;
	}
	public void setCar(Car car) {
		this.car = car;
	}
}

Test类

package lovo;

public class Test {

public static void main(String[] args) {
	try {
		Person p1=new Person("李四", 11, new Car("长城", 112));
		Person p2=MyUtil.clone(p1);
		p2.getCar().setBrand("大众");
		p2.setAge(22);
		System.out.println(p1);
		
		System.out.println(p2);
	} catch (Exception e) {
		// TODO: handle exception
		e.printStackTrace();
	}
}
}
结果:
Person [name=李四, age=11, car=Car [brand=长城, maxSpeed=112]]
Person [name=李四, age=22, car=Car [brand=大众, maxSpeed=112]]

这个时候,你给p2设置值时不会影响p1的值,浅拷贝感觉比较垃圾。那你们可以去看下这位大哥的。

https://blog.csdn.net/tounaobun/article/details/8491392#reply点击打开链接



算了我还是贴一下代码吧

A类 持久化类  里面的什么重写clone啊什么重写toString 啊之类的都是alt+shift+s  看选项搞出来的,不要自己敲代码,我最开始学代码的时候精力都花去记这些鬼东西去了。实际上都是可以用机器搞出来的,不多说,贴代码了。

package lovq;

public class A implements Cloneable{

	private int number;

	@Override
	public String toString() {
		return "[number=" + number + "]";
	}

	public int getNumber() {
		return number;
	}

	public void setNumber(int number) {
		this.number = number;
	}

	@Override
	protected Object clone() throws CloneNotSupportedException {
		// TODO Auto-generated method stub
		return super.clone();
	}



	
	
}

Test类

package lovq;

public class Test {

	public static void main(String[] args) throws CloneNotSupportedException {
		A a=new A();
		a.setNumber(123456);
		A b=(A) a.clone();
		
		System.out.println("a的值"+a);
		System.out.println("b的值"+b);
		b.setNumber(22555);//改变b的值看一下会不会影响A的值,这才是克隆
		System.out.println("a的值"+a);
		System.out.println("b的值"+b);
	}
}
结果:
a的值[number=123456]
b的值[number=123456]
a的值[number=123456]
b的值[number=22555]

好了,这两种方法就是java里关于复制的最核心的。有什么问题或者想交流的可以在留言区发言,我会及时回复。



下面是一些废话,可以不用看的》

还没说完,为什么要用这两种方法,用复制变量哪种方法行不行呢?当然不行。还是去看这个人的博客吧,我不想抄。我还是贴一下吧!

假设说我是一个beginner,我会这样写:

[java] view plain copy
  1. class Student {  
  2.     private int number;  
  3.   
  4.     public int getNumber() {  
  5.         return number;  
  6.     }  
  7.   
  8.     public void setNumber(int number) {  
  9.         this.number = number;  
  10.     }  
  11.       
  12. }  
  13. public class Test {  
  14.       
  15.     public static void main(String args[]) {  
  16.           
  17.         Student stu1 = new Student();  
  18.         stu1.setNumber(12345);  
  19.         Student stu2 = stu1;  
  20.           
  21.         System.out.println("学生1:" + stu1.getNumber());  
  22.         System.out.println("学生2:" + stu2.getNumber());  
  23.     }  
  24. }  


打印结果:

[plain] view plain copy
  1. 学生1:12345  
  2. 学生2:12345  

这里我们自定义了一个学生类,该类只有一个number字段。

我们新建了一个学生实例,然后将该值赋值给stu2实例。(Student stu2 = stu1;)

再看看打印结果,作为一个新手,拍了拍胸腹,对象复制不过如此,

难道真的是这样吗?


我们试着改变stu2实例的number字段,再打印结果看看:

[java] view plain copy
  1. stu2.setNumber(54321);  
  2.   
  3. System.out.println("学生1:" + stu1.getNumber());  
  4. System.out.println("学生2:" + stu2.getNumber());  

打印结果:

[plain] view plain copy
  1. 学生1:54321  
  2. 学生2:54321  

这就怪了,为什么改变学生2的学号,学生1的学号也发生了变化呢?


原因出在(stu2 = stu1) 这一句。该语句的作用是将stu1的引用赋值给stu2,

这样,stu1和stu2指向内存堆中同一个对象。如图:




posted @ 2018-03-29 17:34  紫紫幽  阅读(380)  评论(0编辑  收藏  举报