Java 中如何使用clone()方法克隆对象?
java为什么要 对象克隆:
在程序开发时,有时可能会遇到以下情况:已经存在一个对象A,现在需要一个与A对象完全相同的B 对象,并对B 对象的属性值进行修改,但是A 对象原有的属性值不能改变。这时,如果使用Java 提供的对象赋值语句,当修改B 对象的属性值后,A 对象的属性值也将被修改。那么应该如何实现创建一个与A 对象完全相同的B 对象,但是改变B对象的属性值时A 对象的属性值不变呢?
专家解答
要实现这一功能,可以使用Object 类中的clone()方法。clone()方法可以用来完成对象的浅克隆。所谓浅克隆就是说被克隆的对象各个属性都是基本类型,而不是引用类型。如果存在引用类型的属性,则需要进行深克隆。下面对这两种克隆方式进行举例说明。
1.浅克隆(1)编写Address 类,首先在该类中定义state(表示国家)、province(表示省)和city(表示市)3 个域,然后在构造方法中初始化这3 个域,并提供getter()和setter()方法用于获得和修改这3 个域,最后重写toString()方法方便输出该类的对象,代码如下:
1.浅克隆(1)编写Address 类,首先在该类中定义state(表示国家)、province(表示省)和city(表示市)3 个域,然后在构造方法中初始化这3 个域,并提供getter()和setter()方法用于获得和修改这3 个域,最后重写toString()方法方便输出该类的对象,代码如下:
地址对象:
package com.nf147.Constroller;
public class Address implements Cloneable {
private String state; //国家
private String province; //省
private String city; //市
public Address() {
}
public Address(String state, String province, String city) {
this.state = state;
this.province = province;
this.city = city;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
@Override
public String toString() { //重写toString
StringBuilder sb=new StringBuilder();
sb.append("国家:"+state+",");
sb.append("省:"+province+",");
sb.append("市:"+city+",");
return sb.toString();
}
}
编写Employee 类,首先在该类中定义name(表示姓名)、age(表示年龄)和address(表示地址)3 个域,然后在构造方法中初始化这3 个域,并提供getter()和setter()方法用于获得和修改这3 个域,再重写toString()方法方便输出该类的对象,最后重写clone()方法来提供克隆的功能,代码如下:
员工:
package com.nf147.Constroller;
public class Employee implements Cloneable {
private String name; //姓名
private int age; //年龄
private Address address; //地址
public Employee(String name, int age, Address address) {
this.name = name;
this.age = age;
this.address = address;
}
public Employee() {
}
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 Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
@Override
public String toString() { //重新toString()方法
return "Employee{" +
"姓名='" + name + '\'' +
", 年龄=" + age +
", 地址=" + address +
'}';
}
public Employee clone() { //实现浅克隆
Employee employee = null;
try {
employee = (Employee) super.clone();
employee.address = address.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return employee;
}
}
测试类:
package com.nf147.Constroller;
public class TestClone {
public static void main(String[] args) {
System.out.println("克隆之前:");
Address address = new Address("中国", "吉林", "长春");
Employee employee1 = new Employee("无语", 32, address);
System.out.println("员工 1 的信息");
System.out.println(employee1);
System.out.println("====================");
System.out.println("克隆之后:");
Employee employee2=employee1.clone();
employee2.getAddress().setState("中国");
employee2.getAddress().setProvince("辽宁");
employee2.getAddress().setCity("大连");
employee2.setName("倾城");
employee2.setAge(33);
System.out.println("员工2 的 信息");
System.out.println(employee2);
System.out.println("员工1的 信息");
System.out.println(employee1);
}
}
截图:

说明:
从图中可以看到,对于引用类型并没有克隆成功。
2.深克隆(1)编写类Address1,在该类中首先定义state(表示国家)、province(表示省)和city(表示市)3 个域,然后在构造方法中初始化这3 个域,并提供了getter()和setter()方法用于获得和修改这3 个域,再重写toString()方法方便输出该类的对象,最后重写clone()方法提供克隆的功能,关键代码如下:
package com.nf147.Constroller;
public class Address implements Cloneable {
private String state; //国家
private String province; //省
private String city; //市
public Address() {
}
public Address(String state, String province, String city) {
this.state = state;
this.province = province;
this.city = city;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
@Override
public String toString() { //重写toString
StringBuilder sb=new StringBuilder();
sb.append("国家:"+state+",");
sb.append("省:"+province+",");
sb.append("市:"+city+",");
return sb.toString();
}
@Override
protected Address clone(){
Address address = null;
try{
address=(Address)super.clone();
}catch (CloneNotSupportedException e){
e.printStackTrace();
}
return address;
}
}
说明:
Address 类的域不是基本类型就是不可变类型,所以可以直接使用浅克隆。
(2)编写Employee类,首先在该类中定义name(表示姓名)、age(表示年龄)和address(表示地址)3 个域,然后在构造方法中初始化这3 个域,并提供getter()和setter()方法用于获得和修改这3 个域,再重写toString()方法方便输出该类的对象,最后重写clone()方法来提供克隆的功能。代码如下:
package com.nf147.Constroller;
public class Employee implements Cloneable {
private String name; //姓名
private int age; //年龄
private Address address; //地址
public Employee(String name, int age, Address address) {
this.name = name;
this.age = age;
this.address = address;
}
public Employee() {
}
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 Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
@Override
public String toString() { //重新toString()方法
return "Employee{" +
"姓名='" + name + '\'' +
", 年龄=" + age +
", 地址=" + address +
'}';
}
public Employee clone() { //实现浅克隆
Employee employee = null;
try {
employee = (Employee) super.clone();
employee.address = address.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return employee;
}
}
测试:
package com.nf147.Constroller;
public class TestClone {
public static void main(String[] args) {
System.out.println("克隆之前:");
Address address = new Address("中国", "吉林", "长春");
Employee employee1 = new Employee("无语", 32, address);
System.out.println("员工 1 的信息");
System.out.println(employee1);
System.out.println("====================");
System.out.println("克隆之后:");
Employee employee2=employee1.clone();
employee2.getAddress().setState("中国");
employee2.getAddress().setProvince("辽宁");
employee2.getAddress().setCity("大连");
employee2.setName("倾城");
employee2.setAge(33);
System.out.println("员工2 的 信息");
System.out.println(employee2);
System.out.println("员工1的 信息");
System.out.println(employee1);
}
}
截图:

Java 中如何使用clone()方法克隆对象?的更多相关文章
- Java clone() 方法克隆对象——深拷贝与浅拷贝
基本数据类型引用数据类型特点 1.基本数据类型的特点:直接存储在栈(stack)中的数据 2.引用数据类型的特点:存储的是该对象在栈中引用,真实的数据存放在堆内存里 引用数据类型在栈中存储了指针,该指 ...
- 关于Java的Object.clone()方法与对象的深浅拷贝
文章同步更新在个人博客:关于Java的Object.clone()方法与对象的深浅拷贝 引言 在某些场景中,我们需要获取到一个对象的拷贝用于某些处理.这时候就可以用到Java中的Object.clon ...
- Object.clone()方法与对象的深浅拷贝
转载:[https://www.cnblogs.com/nickhan/p/8569329.html] 引言 在某些场景中,我们需要获取到一个对象的拷贝用于某些处理.这时候就可以用到Java中的Obj ...
- 方法object面试题分析:7JAVA中Object的clone方法详解-克隆-深克隆
时间紧张,先记一笔,后续优化与完善. 每日一道理 翻开早已发黄的页张,试着寻找过去所留下的点点滴滴的足迹.多年前的好友似乎现在看来已变得陌生,匆忙之间,让这维持了多年的友谊变淡,找不出什么亲切 ...
- Java中直接输出一个类的对象
例如 package com.atguigu.java.fanshe; public class Person { String name; private int age; public Strin ...
- java中substring的使用方法
java中substring的使用方法 str=str.substring(int beginIndex);截取掉str从首字母起长度为beginIndex的字符串,将剩余字符串赋值给str: str ...
- Java中Set的contains()方法
Java中Set的contains()方法 -- hashCode与equals方法的约定及重写原则 翻译人员: 铁锚 翻译时间: 2013年11月5日 原文链接: Java hashCode() a ...
- Java中Set的contains()方法——hashCode与equals方法的约定及重写原则
转自:http://blog.csdn.net/renfufei/article/details/14163329 翻译人员: 铁锚 翻译时间: 2013年11月5日 原文链接: Java hashC ...
- java中equals和hashCode方法随笔二
前几天看了篇关于java中equals和hashCode方法的解析 1.Object类中的equals方法和hashCode方法. Object类中的equals和hashCode方法简单明了,所有的 ...
随机推荐
- CAS单点登录系统--进阶
2.CAS服务端数据源设置 2.1需求分析 我们现在让用户名密码从我们的优乐选的user表里做验证 2.2配置数据源 (1)修改cas服务端中web-inf下deployerConfigContext ...
- python内存管理(通俗易懂,详细可靠)
python内存管理 python3.6.9 内存管理的官方文档 https://docs.python.org/zh-cn/3.6/c-api/memory.html 一.变量存哪了? x = 10 ...
- 一分钟搭建 Web 版的 PHP 代码调试利器
一.背景 俗话说:"工欲善其事,必先利其器".作为一门程序员,我们在工作中,经常需要调试某一片段的代码,但是又不想打开繁重的 IDE (代码编辑器).使用在线工具调试代码有时有 ...
- mysql时间类型
转自:http://www.cnblogs.com/Matrix54/archive/2012/05/01/2478158.html AVA中获取当前系统时间 一. 获取当前系统时间和日期并格式化输出 ...
- linux的管道 |和grep命令以及一些其他命令(diff,echo,cat,date,time,wc,which,whereis,gzip,zcat,unzip,sort)
linux提供管道符号“|”,作用是命令1的输出内容作为命令2的输入内容.通常与grep命令一起使用. 格式:命令1 |命令2 grep命令:全称为global regular expression ...
- 50. Pow(x, n) (JAVA)
Implement pow(x, n), which calculates x raised to the power n(xn). Example 1: Input: 2.00000, 10 Out ...
- xcode自动生成代码片段
一.什么是代码片段 当在Xcode中输入dowhile并回车后,Xcode会出现下图所示的提示代码: 这就是代码片段,目的是使程序员以最快的速度输入常用的代码片段,提高编程效率.该功能是从Xcode4 ...
- 一、SignalR使用心得
一.通讯模式 以往,我们聊天发消息模式(单体发送消息或通知)-好友(一对一).群组(一对多),方便管理好友-分组方式. 那么聊天和好友管理参考qq,刷新分组标签也页面就会从新加载分组列表和分组内好友列 ...
- PAT Basic 1048 数字加密 (20 分)
本题要求实现一种数字加密方法.首先固定一个加密用正整数 A,对任一正整数 B,将其每 1 位数字与 A 的对应位置上的数字进行以下运算:对奇数位,对应位的数字相加后对 13 取余——这里用 J 代表 ...
- Qt的ui->setupUi(this)在做什么?
ui->setupUi() 新建好Qt的工程之后,总是会在MainWindow函数中有一行代码 ui->setupUi(this); 跟踪进这行代码 class Ui_MainWindow ...