对象的克隆是java的一项高级技术,他可以根据给定的对象,获得与其完全相同的另一个对象。

1.浅克隆主要是复制对象的值

2.深克隆:当类存在聚合关系的时候,克隆就必须考虑聚合对象的克隆,可以复制引用类型的字段。

一、常见的错误:

Employee 类

package text1;

public class Employee {
private String name;
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;
}
private int age;
public String toString(){
return "姓名"+name+"年龄: "+age;
}
}

Test

package text1;

public class Test {

    public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("克隆前");
Employee employee1=new Employee();
employee1.setName("张三丰");
employee1.setAge();
System.out.println(employee1);
System.out.println("克隆后");
Employee employee2=employee1;
employee2.setName("王二小");
employee2.setAge();
System.out.println("输出员工一的信息");
System.out.println(employee1);
System.out.println("输出第二个员工的信息");
System.out.println(employee2);
} }

java中,对于基本类型可以使用 "="来克隆,此时两个变量除了相等时没有任何关系的。

而在引用类型却不能简单地使用“=”进行克隆,这与java内存空间的使用有关。java将内存分为两块,堆和栈。

在栈中保存基本类型和引用变量,堆中保存对象。对于引用变量而言,使用“=”将修改引用,而不是复制堆中的对象,此时两个引用

变量将指向同一个对象,因此,如果一个变量对其进行修改将改变另一个变量。

说白了就是指向同一个对象。。。假克隆

二、java对象的浅克隆

如果对象是基本类型,则采用浅克隆就行,如果对象的成员变量包括可引用类型,需要深克隆。

***如果引用类型不变,String类的对象,则不需要深克隆

Address类;

public class Address {
private String state;
private String province;
private String city; public void setState(String state) {
this.state = state;
}
public void setProvince(String province) {
this.province = province;
}
public void setCity(String city) {
this.city = city;
} public Address(String state,String province,String city){
this.state=state;
this.province=province;
this.city=city;
}
//@Override
public String toString(){
StringBuilder sb=new StringBuilder();
sb.append("国家 :"+state+",\n");
sb.append("省 "+province+",\n");
sb.append("市 "+city);
return sb.toString();
} }

Employee类:

package text6;

public class Employee implements Cloneable{
private String name;
private int age;
private Address address;
public Address getAddress() {
return address;
} public void setName(String name) {
this.name = name;
} public void setAge(int age) {
this.age = age;
}
public void setAddress(Address address) {
this.address = address;
} public Employee(String name,int age,Address address){
this.name=name;
this.age=age;
this.address=address;
}
public Employee clone(){
Employee employee=null;
try{
employee=(Employee)super.clone();
}catch(CloneNotSupportedException e){
e.printStackTrace();
}
return employee;
}
public String toString(){
StringBuilder sb=new StringBuilder();
sb.append("姓名 "+name+",\n");
sb.append("年龄 "+age+",\n");
sb.append("地址 \n"+address);
return sb.toString();
} }

Test

package text6;

public class Text {

    public static void main(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);
} }

浅克隆:创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型属性,仍指向原有属性所指向的对象的内存地址。

深克隆:创建一个新对象,属性中引用的其他对象也会被克隆,不再指向原有对象地址。

总之深浅克隆都会在堆中新分配一块区域,区别在于对象属性引用的对象是否需要进行克隆(递归性的)。

三、深克隆

Address类

package text7;

/*引用对象不可变的不必进行深克隆
* 如果类成员变量包括可以引用的类型
则在克隆时候就需要进行深克隆
*/
public class Address implements Cloneable {
private String state;
private String province;
private String city; public void setState(String state) {
this.state = state;
} public void setProvince(String province) {
this.province = province;
} public void setCity(String city) {
this.city = city;
} public Address(String state, String province, String city) {
this.state = state;
this.province = province;
this.city = city;
} // @Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("国家 :" + state + ",");
sb.append("省 " + province + ",");
sb.append("市 " + city);
return sb.toString();
} protected Address clone() {
Address address = null;
try {
address = (Address) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return address;
}
}

Employee类:

package text7;

public class Employee implements Cloneable{
private String name;
private int age;
private Address address;
public Address getAddress() {
return address;
} public void setName(String name) {
this.name = name;
} public void setAge(int age) {
this.age = age;
}
public void setAddress(Address address) {
this.address = address;
} public Employee(String name,int age,Address address){
this.name=name;
this.age=age;
this.address=address;
}
public Employee clone(){
Employee employee=null;
try{
employee=(Employee)super.clone();
employee.address=address.clone();
}catch(CloneNotSupportedException e){
e.printStackTrace();
}
return employee;
} public String toString(){
StringBuilder sb=new StringBuilder();
sb.append("姓名 "+name+",\n");
sb.append("年龄 "+age+",\n");
sb.append("地址 \n"+address);
return sb.toString();
} }

Test

package text7;

public class Test {

    public static void main(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); }
}

java 浅克隆 深克隆的更多相关文章

  1. Java克隆--深克隆与浅克隆的区别

    克隆,就是复制一个对象的副本,而克隆又分浅克隆和深克隆.浅克隆是指克隆得到的对象基本类型的值改变了,而源对象的值不会变.但如果被克隆对象引用类型的值改变了,那么源对象的值同样会改变,因为引用类型在栈内 ...

  2. java浅克隆和深克隆,序列化和反序列化实现深克隆(封装序列化和反序列化操作)

    本篇博客内容: 一.浅克隆(ShallowClone)和深克隆(DeepClone) 二.序列化和反序列化实现深克隆 三.封装序列化和反序列化操作 ObjectOutputStream + 内存流By ...

  3. java 浅克隆(浅复制)和深克隆(深复制)

    http://www.voidcn.com/blog/u011380813/article/p-6161450.html https://gold.xitu.io/entry/570d89651ea4 ...

  4. Java实现深克隆的两种方式

    序列化和依次克隆各个可变的引用类型都可以实现深克隆,但是序列化的效率并不理想 下面是两种实现深克隆的实例,并且测试类对两种方法进行了对比: 1.重写clone方法使用父类中的clone()方法实现深克 ...

  5. Java基础--深克隆补充

    深克隆文章很多,这里推荐Java提高篇--对象克隆(复制). 以上文章条理清晰,一目了然,但最近在项目中碰到的实际问题是,所要克隆的对象是加上子类父类共计207个,无论用上述两种方式的哪一种,都要一一 ...

  6. 深入理解Java对象的创建过程:类的初始化与实例化

    摘要: 在Java中,一个对象在可以被使用之前必须要被正确地初始化,这一点是Java规范规定的.在实例化一个对象时,JVM首先会检查相关类型是否已经加载并初始化,如果没有,则JVM立即进行加载并调用类 ...

  7. Java对象的克隆和深浅问题

    Java实现克隆的方式 Java实现克隆的方式有如下两种, 推荐采用实现Cloneable接口的方式 实现Cloneable接口, 重写clone方法, 调用父类的clone方法 还有另一种方法, 不 ...

  8. 《practical Java》读书笔记

    题记: 花了一周把Peter Haggar的<practical Java>看了遍,有所感悟,年纪大了, 写下笔记,方便日后查看.也希望有缘之人可以看看,做个渺小的指路人. 不足之处还望指 ...

  9. java 的原型模式和clone

    原型模式是一种创建型设计模式,在java中可以直接调用object.clone(). 原型模式属于对象的创建模式.通过给出一个原型对象来指明所有创建的对象的类型,然后用复制这个原型对象的办法创建出更多 ...

随机推荐

  1. spring4笔记----“零配置”:spring提供的几个Annotation标注

    @Component  :标注一个普通的Spring Bean类 @Controller    :标注一个控制器组件器 @Service        :标注一个业务逻辑组件器 @Repository ...

  2. Java中的生产消费者问题

    package day190109; import java.util.LinkedList; import java.util.Queue; import java.util.Random; pub ...

  3. Linux进程调度策略的发展和演变--Linux进程的管理与调度(十六)

    1 前言 1.1 进程调度 内存中保存了对每个进程的唯一描述, 并通过若干结构与其他进程连接起来. 调度器面对的情形就是这样, 其任务是在程序之间共享CPU时间, 创造并行执行的错觉, 该任务分为两个 ...

  4. c/c++ 标准库 string

    c/c++ 标准库 string 标准库 string的小例子 test1~test10 #include <iostream> using namespace std; int main ...

  5. 编写脚本实现DHCP服务与DHCP中继自动化执行

    编写脚本实现DHCP服务与DHCP中继自动化执行 本脚本是在liunx搭建DHCP服务器以及DHCP中继服务器实验环境下实现的https://www.cnblogs.com/yuzly/p/10539 ...

  6. GET vs. POST

    GET 和 POST 都创建数组(例如,array( key => value, key2 => value2, key3 => value3, ...)).此数组包含键/值对,其中 ...

  7. LeetCode算法题-String Compression(Java实现)

    这是悦乐书的第230次更新,第242篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第97题(顺位题号是443).给定一组字符,就地压缩它.压缩后的长度必须始终小于或等于原 ...

  8. 4、爬虫系列之mongodb

    mongodb mongo简介 简介 MongoDB是一个基于分布式文件存储的数据库.由C++语言编写.旨在为WEB应用提供可扩展的高性能数据存储解决方案.MongoDB是一个介于关系数据库和非关系数 ...

  9. WPF画图の利用Path画扇形(仅图形)

    一.画弧 Path继承自Sharp,以System.Windows.Shapes.Shape为基类,它是一个具有各种方法的控件. 我们先看一段xaml代码: <Path Stroke=" ...

  10. 机器学习算法总结(六)——EM算法与高斯混合模型

    极大似然估计是利用已知的样本结果,去反推最有可能(最大概率)导致这样结果的参数值,也就是在给定的观测变量下去估计参数值.然而现实中可能存在这样的问题,除了观测变量之外,还存在着未知的隐变量,因为变量未 ...