Java都继承自Object,自带clone的native方法,但其实只能实现浅拷贝通过implements Cloneable(虽然是个空方法),通过手工实现clone,才能实现深度拷贝。
容易发生误用的情况,
类变量是个类情况下,以为只要类变量实现了clone方法,就可以实现类的深拷贝,其实,这个时候也要
在clone方法中对类变量进行clone,否则还是浅拷贝。废话少说,代码如下:
1、没有实现clone的情况
public class Dog {
public int legCounts;
public Dog(int legCounts) {
this.legCounts = legCounts;
}
public void changeLegCounts() {
this.legCounts *= 2;
}
public String toString() {
return Integer.toString(legCounts);
}
}
public class GouClone implements Cloneable {
public int legCounts;
Dog dog = new Dog(4);
protected GouClone clone() throws CloneNotSupportedException {
return (GouClone)super.clone();
}
}
public class Client {
public static void main(String[] args) throws CloneNotSupportedException {
// TODO Auto-generated method stub
GouClone gouClone = new GouClone();
gouClone.legCounts = 3;
System.out.println("原拷贝狗腿的数量:" + gouClone.legCounts);
System.out.println("原普通狗的数量:" + gouClone.dog);
GouClone gouClone1 = (GouClone)gouClone.clone();
gouClone1.legCounts = 2;
Dog dog = gouClone1.dog;
dog.changeLegCounts();
System.out.println("拷贝后,原来普通狗的数量:" + gouClone.dog);
System.out.println("拷贝后,拷贝狗腿的数量:" + gouClone1.legCounts);
System.out.println("拷贝后,普通狗的数量:" + gouClone1.dog);
}
}
结果是:
原拷贝狗腿的数量:3
原普通狗腿的数量:4
拷贝后,原来普通狗的数量:8
拷贝后,拷贝狗腿的数量:2
拷贝后,普通狗的数量:8
2、只实现了clone方法,类变量没有clone
public class Dog implements Cloneable {
public int legCounts;
public Dog(int legCounts) {
this.legCounts = legCounts;
}
public void changeLegCounts() {
this.legCounts *= 2;
}
public Dog clone() throws CloneNotSupportedException {
return (Dog)super.clone();
}
public String toString() {
return Integer.toString(this.legCounts);
}
}
public class GouClone implements Cloneable {
public int legCounts;
Dog dog = new Dog(4);
protected GouClone clone() throws CloneNotSupportedException {
GouClone clone = (GouClone)super.clone();
return clone;
}
}
public class Client {
public static void main(String[] args) throws CloneNotSupportedException {
// TODO Auto-generated method stub
GouClone gouClone = new GouClone();
gouClone.legCounts = 3;
System.out.println("原拷贝狗腿的数量:" + gouClone.legCounts);
System.out.println("原普通狗的数量:" + gouClone.dog);
GouClone gouClone1 = (GouClone)gouClone.clone();
gouClone1.legCounts = 2;
Dog dog = gouClone1.dog;
dog.changeLegCounts();
System.out.println("拷贝后,原来普通狗的数量:" + gouClone.dog);
System.out.println("拷贝后,拷贝狗腿的数量:" + gouClone1.legCounts);
System.out.println("拷贝后,普通狗的数量:" + gouClone1.dog);
}
}
结果是:
原拷贝狗腿的数量:3
原普通狗腿的数量:4
拷贝后,原来普通狗的数量:8
拷贝后,拷贝狗腿的数量:2
拷贝后,普通狗的数量:8
3、类变量也在clone中体现,真正实现深拷贝
public class Dog implements Cloneable {
public int legCounts;
public Dog(int legCounts) {
this.legCounts = legCounts;
}
public void changeLegCounts() {
this.legCounts *= 2;
}
public Dog clone() throws CloneNotSupportedException {
return (Dog)super.clone();
}
public String toString() {
return Integer.toString(this.legCounts);
}
}
public class GouClone implements Cloneable {
public int legCounts;
Dog dog = new Dog(4);
protected GouClone clone() throws CloneNotSupportedException {
GouClone clone = (GouClone)super.clone();
clone.dog = clone.dog.clone();
return clone;
}
}
public class Client {
public static void main(String[] args) throws CloneNotSupportedException {
// TODO Auto-generated method stub
GouClone gouClone = new GouClone();
gouClone.legCounts = 3;
System.out.println("原拷贝狗腿的数量:" + gouClone.legCounts);
System.out.println("原普通狗的数量:" + gouClone.dog);
GouClone gouClone1 = (GouClone)gouClone.clone();
gouClone1.legCounts = 2;
Dog dog = gouClone1.dog;
dog.changeLegCounts();
System.out.println("拷贝后,原来普通狗的数量:" + gouClone.dog);
System.out.println("拷贝后,拷贝狗腿的数量:" + gouClone1.legCounts);
System.out.println("拷贝后,普通狗的数量:" + gouClone1.dog);
}
}
结果是:
原拷贝狗腿的数量:3
原普通狗的数量:4
拷贝后,原来普通狗的数量:4
拷贝后,拷贝狗腿的数量:2
拷贝后,普通狗的数量:8
当然,除了类变量clone在clone()方法中体现,也可以通过引用类实现Serializable接口,并在clone()方法中将对象从流中取出,也是一个办法。
分享到:
相关推荐
java8 误用Java 8 新功能的常见误用和其他错误。Java 8 已经存在一段时间了,我们中的许多人已经在项目中使用 Java 8 功能。但是,我们是否正确有效地使用了这些出色的 Java 8 功能?在过去几年进行了大量代码审查后...
然而,API的误用常常导致代码缺陷,给软件开发和维护带来诸多挑战。由于API的复杂性和相关文档资料的缺失,开发人员可能无法充分理解API的正确使用方式,从而导致误用API,进而产生缺陷。为了有效地检测和预防API...
Java 17,也被称为Java SE 17(Java Standard Edition 17),是Oracle公司推出的Java开发平台的最新稳定版本。此版本的发布旨在提供更高效、安全且可靠的编程环境,同时也包含了一系列的新特性、增强功能以及对现有...
### 关于Java内存泄露问题解决 #### 引言:Java内存管理的核心——垃圾回收机制(GC) Java作为当今产业界和学术界最炙手可热的编程语言之一,以其独特的安全性和可移植性赢得了广泛的应用,尤其是在服务器端编程...
评估自动程序修复功能以修复API误用_Java_Python_下载.zip
JAVA不直接允许程序员操控指针,而是通过自动的内存管理机制,比如垃圾回收(Garbage Collection),来避免C++中因指针误用导致的系统崩溃。这种设计提高了JAVA程序的安全性和稳定性,但也意味着JAVA程序员失去了对...
- **易犯错误的关键字**:列出了一些容易被误用的Java关键字。 - **注释的使用**:介绍了不同类型的注释及其在代码中的作用。 - **3.2 原始类型** - **int与Integer的区别**:解释了int作为基本类型与Integer...
Java_Tink是一个强大的开源库,它的目标是让加密变得更加安全、简单且难以误用。这个库不仅限于Java,还支持多种编程语言,实现了跨平台的兼容性,从而为开发者提供了一种统一的方式来处理加密任务。Java_Tink的核心...
* free关键字的误用:Java中不使用free关键字来回收内存对象,而是由垃圾回收机制自动管理 * return语句的使用:在方法中返回值 八、Java面向对象编程 * 面向对象编程的基本概念:继承、多态、封装 * 面向对象编程...
这种方式比传统的常量定义更安全,因为枚举类型的实例是不可变的,避免了值的误用或篡改。通过定义`Direction`枚举,可以方便地处理坦克的移动和射击方向,使代码更加结构化和易于理解。 2. **颜色修正**: 坦克和...
《Java Bug模式详解》这本书是面向那些已经具备Java编程基础的开发者,旨在帮助他们更好地理解和解决在编程过程中遇到的各种错误和异常,提升代码质量和维护效率。书中深入剖析了Java编程中常见的bug模式,通过实例...
7. **新的集合工厂方法**:Java 8在集合接口中添加了工厂方法,如`List.of()`、`Set.of()`和`Map.of()`, 可以方便地创建不可变集合,避免了常见的空构造器和add方法的误用。 8. **接口的私有方法和静态方法**:Java...
- 指针:Java取消了指针概念,避免了因误用指针而导致的潜在安全问题。 - 多重继承:Java仅支持单一继承,但可以通过接口实现多继承的功能。 - 操作符重载:C++支持操作符重载,而Java则没有这一特性。 2. **Java...
悬架系统的设计需要考虑到各种工况,包括常规行驶时的起停、转向、加速和减速,以及在不规范驾驶情况下的误用工况,如通过障碍物等。悬架系统的部件之一,前下摆臂在承受复杂受力情况时,若应力超过材料的许用应力,...
- **指针**:Java不支持指针,避免了因误用指针带来的安全问题。 - **头文件**:Java无需使用头文件来声明类和方法。 - **结构体、联合体和类型定义**:Java不支持C/C++中的结构体、联合体等特性。 - **函数、指针和...
综上所述,Java基础方面的陷阱涵盖了语法理解、数据类型使用、运算符和流程控制的误用、异常处理的不当、内存管理的误区,以及面向对象设计原则的应用等多个方面。通过深入学习和实践,可以有效地避免这些陷阱,提升...
Java面向对象编程(Object-Oriented Programming,简称OOP)是Java编程的核心,它通过封装、继承和多态三大特性来构建高效的代码结构。在Java OOP中,封装是首要原则,它允许我们隐藏实现细节,只对外提供必要的接口...
【标题】:“java+++mysql++BS结构的进销存系统Java源码”指的是一个基于Java编程语言,并结合MySQL数据库开发的Browser/Server(B/S)架构的进销存管理系统源代码。进销存系统主要用于企业管理商品的进货、销售和...
// 此导入并非用于获取系统时间,可能是示例中的误用。 import java.util.*; public class TestTime { Timer timer = new Timer(); // 定义了一个计时器对象,但未在示例中使用。 Calendar c = Calendar....