对象的克隆是java的一项高级技术,他可以根据给定的对象,获得与其完全相同的另一个对象。
1.浅克隆主要是复制对象的值
2.深克隆:当类存在聚合关系的时候,克隆就必须考虑聚合对象的克隆,可以复制引用类型的字段。
一、常见的错误:
Employee 类
package text1;public classEmployee {privateString name;publicString getName() {returnname;
}public voidsetName(String name) {this.name =name;
}public intgetAge() {returnage;
}public void setAge(intage) {this.age =age;
}private intage;publicString toString(){return "姓名"+name+"年龄:"+age;
}
}
View Code
Test
package text1;public classTest {public static voidmain(String[] args) {//TODO Auto-generated method stub
System.out.println("克隆前");
Employee employee1=newEmployee();
employee1.setName("张三丰");
employee1.setAge(17);
System.out.println(employee1);
System.out.println("克隆后");
Employee employee2=employee1;
employee2.setName("王二小");
employee2.setAge(19);
System.out.println("输出员工一的信息");
System.out.println(employee1);
System.out.println("输出第二个员工的信息");
System.out.println(employee2);
}
}
View Code
java中,对于基本类型可以使用 "="来克隆,此时两个变量除了相等时没有任何关系的。
而在引用类型却不能简单地使用“=”进行克隆,这与java内存空间的使用有关。java将内存分为两块,堆和栈。
在栈中保存基本类型和引用变量,堆中保存对象。对于引用变量而言,使用“=”将修改引用,而不是复制堆中的对象,此时两个引用
变量将指向同一个对象,因此,如果一个变量对其进行修改将改变另一个变量。
说白了就是指向同一个对象。。。假克隆
二、java对象的浅克隆
如果对象是基本类型,则采用浅克隆就行,如果对象的成员变量包括可引用类型,需要深克隆。
***如果引用类型不变,String类的对象,则不需要深克隆
Address类;
public classAddress {privateString state;privateString province;privateString city;public voidsetState(String state) {this.state =state;
}public voidsetProvince(String province) {this.province =province;
}public voidsetCity(String city) {this.city =city;
}publicAddress(String state,String province,String city){this.state=state;this.province=province;this.city=city;
}//@Override
publicString toString(){
StringBuilder sb=newStringBuilder();
sb.append("国家 :"+state+",\n");
sb.append("省"+province+",\n");
sb.append("市"+city);returnsb.toString();
}
}
View Code
Employee类:
packagetext6;public class Employee implementsCloneable{privateString name;private intage;privateAddress address;publicAddress getAddress() {returnaddress;
}public voidsetName(String name) {this.name =name;
}public void setAge(intage) {this.age =age;
}public voidsetAddress(Address address) {this.address =address;
}public Employee(String name,intage,Address address){this.name=name;this.age=age;this.address=address;
}publicEmployee clone(){
Employee employee=null;try{
employee=(Employee)super.clone();
}catch(CloneNotSupportedException e){
e.printStackTrace();
}returnemployee;
}publicString toString(){
StringBuilder sb=newStringBuilder();
sb.append("姓名 "+name+",\n");
sb.append("年龄 "+age+",\n");
sb.append("地址 \n"+address);returnsb.toString();
}
}
View Code
Test
packagetext6;public classText {public static voidmain(String[] args) {//TODO Auto-generated method stub
System.out.println("克隆之前");
Address address= new Address("中国", "吉林", "长春");
Employee employee1= new Employee("张三丰", 30, address);
System.out.println(employee1);
System.out.println("克隆后");
Employee employee2=employee1.clone();
employee2.getAddress().setState("中国"); //getaddres没有定义
employee2.getAddress().setCity("成都");
employee2.getAddress().setProvince("四川");
System.out.println(employee1);
System.out.println(employee2);
}
}
View Code
浅克隆:创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型属性,仍指向原有属性所指向的对象的内存地址。
深克隆:创建一个新对象,属性中引用的其他对象也会被克隆,不再指向原有对象地址。
总之深浅克隆都会在堆中新分配一块区域,区别在于对象属性引用的对象是否需要进行克隆(递归性的)。
三、深克隆
Address类
packagetext7;/*引用对象不可变的不必进行深克隆
* 如果类成员变量包括可以引用的类型
则在克隆时候就需要进行深克隆*/
public class Address implementsCloneable {privateString state;privateString province;privateString city;public voidsetState(String state) {this.state =state;
}public voidsetProvince(String province) {this.province =province;
}public voidsetCity(String city) {this.city =city;
}publicAddress(String state, String province, String city) {this.state =state;this.province =province;this.city =city;
}//@Override
publicString toString() {
StringBuilder sb= newStringBuilder();
sb.append("国家 :" + state + ",");
sb.append("省 " + province + ",");
sb.append("市 " +city);returnsb.toString();
}protectedAddress clone() {
Address address= null;try{
address= (Address) super.clone();
}catch(CloneNotSupportedException e) {
e.printStackTrace();
}returnaddress;
}
}
View Code
Employee类:
packagetext7;public class Employee implementsCloneable{privateString name;private intage;privateAddress address;publicAddress getAddress() {returnaddress;
}public voidsetName(String name) {this.name =name;
}public void setAge(intage) {this.age =age;
}public voidsetAddress(Address address) {this.address =address;
}public Employee(String name,intage,Address address){this.name=name;this.age=age;this.address=address;
}publicEmployee clone(){
Employee employee=null;try{
employee=(Employee)super.clone();
employee.address=address.clone();
}catch(CloneNotSupportedException e){
e.printStackTrace();
}returnemployee;
}publicString toString(){
StringBuilder sb=newStringBuilder();
sb.append("姓名 "+name+",\n");
sb.append("年龄 "+age+",\n");
sb.append("地址 \n"+address);returnsb.toString();
}
}
View Code
Test
packagetext7;public classTest {public static voidmain(String[] args) {//TODO Auto-generated method stub
System.out.println("克隆前");
Address address= new Address("中国", "吉林", "长春");
Employee employee1= new Employee("张三丰", 30, address);
System.out.println("员工一信息");
System.out.println(employee1);
System.out.println("克隆后");
Employee employee2=employee1.clone();
employee2.getAddress().setState("中国");
employee2.getAddress().setProvince("四川");
employee2.getAddress().setCity("成都");
employee2.setName("李云龙");
employee2.setAge(24);
System.out.println("员工一信息");
System.out.println(employee1);
System.out.println("员工二信息");
System.out.println(employee2);
}
}
View Code