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()方法克隆对象?的更多相关文章

  1. Java clone() 方法克隆对象——深拷贝与浅拷贝

    基本数据类型引用数据类型特点 1.基本数据类型的特点:直接存储在栈(stack)中的数据 2.引用数据类型的特点:存储的是该对象在栈中引用,真实的数据存放在堆内存里 引用数据类型在栈中存储了指针,该指 ...

  2. 关于Java的Object.clone()方法与对象的深浅拷贝

    文章同步更新在个人博客:关于Java的Object.clone()方法与对象的深浅拷贝 引言 在某些场景中,我们需要获取到一个对象的拷贝用于某些处理.这时候就可以用到Java中的Object.clon ...

  3. Object.clone()方法与对象的深浅拷贝

    转载:[https://www.cnblogs.com/nickhan/p/8569329.html] 引言 在某些场景中,我们需要获取到一个对象的拷贝用于某些处理.这时候就可以用到Java中的Obj ...

  4. 方法object面试题分析:7JAVA中Object的clone方法详解-克隆-深克隆

    时间紧张,先记一笔,后续优化与完善.     每日一道理 翻开早已发黄的页张,试着寻找过去所留下的点点滴滴的足迹.多年前的好友似乎现在看来已变得陌生,匆忙之间,让这维持了多年的友谊变淡,找不出什么亲切 ...

  5. Java中直接输出一个类的对象

    例如 package com.atguigu.java.fanshe; public class Person { String name; private int age; public Strin ...

  6. java中substring的使用方法

    java中substring的使用方法 str=str.substring(int beginIndex);截取掉str从首字母起长度为beginIndex的字符串,将剩余字符串赋值给str: str ...

  7. Java中Set的contains()方法

    Java中Set的contains()方法 -- hashCode与equals方法的约定及重写原则 翻译人员: 铁锚 翻译时间: 2013年11月5日 原文链接: Java hashCode() a ...

  8. Java中Set的contains()方法——hashCode与equals方法的约定及重写原则

    转自:http://blog.csdn.net/renfufei/article/details/14163329 翻译人员: 铁锚 翻译时间: 2013年11月5日 原文链接: Java hashC ...

  9. java中equals和hashCode方法随笔二

    前几天看了篇关于java中equals和hashCode方法的解析 1.Object类中的equals方法和hashCode方法. Object类中的equals和hashCode方法简单明了,所有的 ...

随机推荐

  1. SpringBoot自定义Starter实现

    自定义Starter: Starter会把所有用到的依赖都给包含进来,避免了开发者自己去引入依赖所带来的麻烦.Starter 提供了一种开箱即用的理念,其中核心就是springboot的自动配置原理相 ...

  2. Java编程思想学习录(连载之:内部类)

    内部类基本概念 可将一个类的定义置于另一个类定义的内部 内部类允许将逻辑相关的类组织在一起,并控制位于内部的类的可见性 甚至可将内部类定义于一个方法或者任意作用域内! 当然,内部类 ≠ 组合 内部类拥 ...

  3. [FJOI2007]轮状病毒 题解(dp(找规律)+高精度)

    [FJOI2007]轮状病毒 题解(dp(找规律)+高精度) 标签:题解 阅读体验:https://zybuluo.com/Junlier/note/1335733 没什么好说的,直接把规律找出来,有 ...

  4. read、readline 和 readlines 的区别?

    假设a.txt的内容如下所示: 1 Hello 2 Welcome 3 What is the fuck... read:读取整个文件. read([size])方法从文件当前位置起读取size个字节 ...

  5. JavaScript的循环结构和经典题目

    一.JS中的循环结构 循环结构的执行步骤1.声明循环变量:2.判断循环条件;3.执行循环体操作:4.更新循环变量:5.然后循环执行2-4,直到条件不成立,跳出循环. while循环()中的表达式,运算 ...

  6. Linux系统性能测试工具(七)——网络性能工具之iperf

    本文介绍关于Linux系统(适用于centos/ubuntu等)的网络性能测试工具-iperf.磁盘io性能测试工具包括: iperf: netperf 参考链接:https://www.cnblog ...

  7. mysql远程连接只显示部分数据库问题

    项目变更了环境,数据库换了环境,所以用navicat连接数据库,结果只能看到部分数据库. 看下高级设置,就只有两个库. 表示很奇怪,难道我的ip被禁止了吗,进入服务器查看连接用户权限 1. 首先查看服 ...

  8. 系统环境: CentOS 64位+千万不要在生产环境中升级glibc!

    # cd /lib64# LD_PRELOAD=/lib64/libc-2.15.so ln -sf /lib64/libc-2.15.so libc.so.6 libc-2.15.so 这个文件名根 ...

  9. STL的容器哈希表

    C++ STL中,哈希表对应的容器是 unordered_map(since C++ 11).根据 C++ 11 标准的推荐,用 unordered_map 代替 hash_map. 与Map的区别 ...

  10. vue 之 双向绑定原理

    一.实现双向绑定 详细版: 前端MVVM实现双向数据绑定的做法大致有如下三种: 1.发布者-订阅者模式(backbone.js) 思路:使用自定义的data属性在HTML代码中指明绑定.所有绑定起来的 ...