JAVA编程思想读书笔记(四)--对象的克隆
No1:
类的克隆
public class MyObject implements Cloneable {
int i; public MyObject(int i) {
this.i = i;
} @Override
protected Object clone() {
Object o = null;
try {
o = super.clone();
} catch (CloneNotSupportedException e) {
System.out.println("MyObject can't clone");
}
return o;
} @Override
public String toString() {
return Integer.toString(i);
}
}
public class LocalCopy {
public static void main(String args[]) {
check1();
check2();
} static MyObject g(MyObject v) {
v.i++;
return v;
} static MyObject f(MyObject v) {
v = (MyObject) v.clone();
v.i++;
return v;
} private static void check1() {
MyObject a = new MyObject(11);
MyObject b = g(a);
if (a == b) {
System.out.println("a==b");
} else {
System.out.println("a!=b");
}
System.out.println("a=" + a);
System.out.println("b=" + b);
} private static void check2() {
MyObject c = new MyObject(47);
MyObject d = f(c);
if (c == d) {
System.out.println("c==d");
} else {
System.out.println("c!=d");
}
System.out.println("c=" + c);
System.out.println("d=" + d);
}
}
输出结果
a==b
a=12
b=12
c!=d
c=47
d=48
若想克隆一个类,必须继承Cloneable,并且重写clone方法
g()演示的是按引用传递,它会修改外部对象,并返回对那个外部对象的一个引用。
f()是对自变量进行克隆,所以将其分离出来,并让原来的对象保持独立,甚至能返回指向这个新对象的一个句柄,而且不会对原来的对象产生任何副作用。
No2:
public class Snake implements Cloneable {
private Snake next;
private char c; Snake(int i, char x) {
c = x;
if (--i > 0) {
next = new Snake(i, (char) (x + 1));
}
} void increment() {
c++;
if (next != null) {
next.increment();
}
} @Override
public String toString() {
String s = ":" + c;
if (next != null) {
s += next.toString();
}
return s;
} @Override
protected Object clone() {
Object o = null;
try {
o = super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return o;
} public static void main(String args[]) {
Snake s = new Snake(5, 'a');
System.out.println("s=" + s);
Snake s2 = (Snake) s.clone();
System.out.println("s2="+s2);
s.increment();
System.out.println("after s.increment:");
System.out.println("s="+s);
System.out.println("s2="+s2);
}
}
输出结果
s=:a:b:c:d:e
s2=:a:b:c:d:e
after s.increment:
s=:b:c:d:e:f
s2=:a:c:d:e:f
这个还需要再研究
No3:
深层复制
public class CloneA implements Cloneable {
private int i; public CloneA(int i) {
this.i = i;
} @Override
protected Object clone() {
Object o = null;
try {
o = super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return o;
}
}
public class CloneB implements Cloneable {
private int j; public CloneB(int j) {
this.j = j;
} @Override
protected Object clone() {
Object o = null;
try {
o = super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return o;
}
}
public class CloneAB implements Cloneable {
private CloneA cloneA;
private CloneB cloneB; public CloneAB(int i, int j) {
cloneA = new CloneA(i);
cloneB = new CloneB(j);
} @Override
protected Object clone() {
CloneAB o = null;
try {
o = (CloneAB) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
o.cloneA = (CloneA) o.cloneA.clone();
o.cloneB = (CloneB) o.cloneB.clone();
return o;
}
}
public class TextAB {
public static void main(String args[]) {
CloneAB ab = new CloneAB(11, 22);
CloneAB r = (CloneAB) ab.clone();
}
}
CloneAB由CloneA和CloneB两个对象合成,为了对其进行深层复制,必须同时克隆里面两个对象的句柄。
No4:
public class A {} public class B {} public class C extends A implements Cloneable {
@Override
protected Object clone() {
Object o = null;
try {
o = super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return o;
}
} public class D extends C {}
public class TextABCD {
public static void main(String args[]) {
A a = new A();
B b = new B();
C c = new C();
D d = new D(); c.clone();
d.clone();
}
}
在添加克隆能力之前,编译器会阻止我们的克隆尝试。一旦在C类中添加了克隆能力,那么C及它的所有后代都可以克隆。
No5:
public class Ordinary {}
public class WrongClone extends Ordinary { @Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
} public class IsCloneable extends Ordinary implements Cloneable {
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class NoMore extends IsCloneable {
@Override
protected Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException();
}
}
final class ReallyNoMore extends NoMore {} public class TryMore extends NoMore {
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
} public class BackOn extends NoMore {
private BackOn duplicate(BackOn b) {
return new BackOn();
} public Object clone() {
return duplicate(this);
}
}
public class CheckCloneable {
static Ordinary tryToClone(Ordinary ord) {
String id = ord.getClass().getName();
Ordinary x = null;
if (ord instanceof Cloneable) {
try {
System.out.println("Attempting " + id);
x = (Ordinary) ((IsCloneable) ord).clone();
System.out.println("Cloned " + id);
} catch (CloneNotSupportedException e) {
System.out.println("Could not clone " + id);
}
}
return x;
} public static void main(String args[]) {
Ordinary[] ord = {new IsCloneable(),
new WrongClone(),
new NoMore(),
new TryMore(),
new BackOn(),
new ReallyNoMore(),
};
Ordinary x = new Ordinary();
for (int i = 0; i < ord.length; i++) {
tryToClone(ord[i]);
}
}
}
输出结果
Attempting IsCloneable
Cloned IsCloneable
Attempting NoMore
Could not clone NoMore
Attempting TryMore
Could not clone TryMore
Attempting BackOn
Cloned BackOn
Attempting ReallyNoMore
Could not clone ReallyNoMore
WrongClone没有继承Cloneable,所以不能克隆
IsCloneable是标准写法,可以克隆
NoMore直接抛异常,所以不能克隆
ReallyNoMore是final类,所以不能克隆
TryMore继承了NoMore直接抛异常,所以不能克隆
BackOn自己生成一个新对象,算是特殊的克隆
总之,如果希望一个类能够克隆
(1)实现Cloneable接口
(2)覆盖clone()
(3)在自己的clone()中调用super.clone()
(4)在自己的clone()中捕获违例
No6:
String的修改是生成了一个新的String对象,包括“+"的使用
JAVA编程思想读书笔记(四)--对象的克隆的更多相关文章
- <Java编程思想>读书笔记(1)-对象导论、一切都是对象
1.面向对象编程:OOP (Object-oriented Programming) 2.Alan Kay 总结的面向对象语言5个基本特性: 1) 万物皆为对象 2) 程序是对象的集合,他们通过发送消 ...
- JAVA编程思想读书笔记(五)--多线程
接上篇JAVA编程思想读书笔记(四)--对象的克隆 No1: daemon Thread(守护线程) 参考http://blog.csdn.net/pony_maggie/article/detail ...
- JAVA编程思想读书笔记(二)--容器
接上篇JAVA编程思想读书笔记(一) 第八章.对象的容纳 No1: java提供了四种类型的集合类:Vector(矢量).BitSet(位集).Stack(堆栈).Hashtable(散列表) No2 ...
- JAVA编程思想读书笔记(三)--RTTI
接上篇JAVA编程思想读书笔记(二) 第十一章 运行期类型判定 No1: 对于作为程序一部分的每个类,它们都有一个Class对象.换言之,每次写一个新类时,同时也会创建一个Class对象(更恰当的说, ...
- Java编程思想读书笔记之内部类
现在是够懒得了,放假的时候就想把这篇笔记写出来,一直拖到现在,最近在读<Java编程思想>,我想会做不止这一篇笔记,因为之前面试的时候总会问道一些内部类的问题,那这本书的笔记就从内部类开始 ...
- Java编程思想读书笔记(一)【对象导论】
2018年1月7日15:45:58 前言 作为学习Java语言的经典之作<Java编程思想>,常常被人提起.虽然这本书出版十年有余,但是内容还是很给力的.很多人说这本书不是很适合初学者,我 ...
- Java编程思想读书笔记(二)【一切都是对象】
begin 2018年1月9日17:06:47 第二章 一切都是对象 Java语言假设我们只进行面向对象的程序设计. 2.1 用引用操纵对象 每种编程语言都有自己的操纵内存元素的方式 操纵内存元素的方 ...
- Java编程思想读书笔记
声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...
- Java编程思想读书笔记之一切皆对象
一切皆对象 Java程序运行时,数据保存到哪里 寄存器 这是最快的保存区域,因为它位于和其他所有保存方式不同的地方:处理器内部.然而,寄存器的数量十分有限,所以寄存器是根据需要由编译器分配.我们对此没 ...
随机推荐
- golang channel状态表
如果我们查看该表,可以察觉到在操作中可能产生问题的地方.这里有三个可能导致阻塞的操作,以及三 个可能导致程序恐慌的操作. 乍看之下,通道的使用上限制很多,但在检查了这个限制产生的动机并熟悉 了通道的使 ...
- LVS三种模式的区别及负载均衡算法
LVS简介 LVS(Linux Virtual Server)即Linux虚拟服务器,是一个虚拟的服务器集群系统,由章文嵩博士在1998年5月成立,在linux2.6+后将lvs自动加入了kernel ...
- 子集系列(一) 传统subset 问题,例 [LeetCode] Subset, Subset II, Bloomberg 的一道面试题
引言 Coding 问题中有时会出现这样的问题:给定一个集合,求出这个集合所有的子集(所谓子集,就是包含原集合中的一部分元素的集合). 或者求出满足一定要求的子集,比如子集中元素总和为定值,子集元素个 ...
- mysql \G
mysql 命令区分大小写.ego (\G) Send command to mysql server, display result vertically. go (\g) ...
- elasticsearch创建索引
1.通过elasticsearch-head 创建 (1)登录localhost:9100 (2)点击复合查询 (3)输入内容 (4)勾选易读,点击验证是否是JSON格式 (5)点击提交请求,返回 { ...
- .Net各版本新特性
序言 C# 1.0 (2002) public interface IDateProvider { DateTime GetDate(); } 隐式接口实现 public class DefaultD ...
- [php]apache虚拟主机配置
1.所谓虚拟主机的配置,即url与磁盘目录的绑定 2.在httpd.conf中查询Virtual host,发现有注释说明需要在conf/extra/httpd-vhosts.conf中进行配置. 3 ...
- LintCode 391: Count Of Airplanes
LintCode 391: Count Of Airplanes 题目描述 给出飞机的起飞和降落时间的列表,用 interval 序列表示. 请计算出天上同时最多有多少架飞机? 样例 对于每架飞机的起 ...
- 【CodeForces】866D. Buy Low Sell High
[题意]已知n天股价,每天可以买入一股或卖出一股或不作为,最后必须持0股,求最大收益. [算法]堆 贪心? [题解] 不作为思想:[不作为=买入再卖出] 根据不作为思想,可以推出中转站思想. 中转站思 ...
- 【洛谷 P3199】 [HNOI2009]最小圈(分数规划,Spfa)
题目链接 一开始不理解为什么不能直接用\(Tarjan\)跑出换直接求出最小值,然后想到了"简单环",恍然大悟. 二分答案,把所有边都减去\(mid\),判是否存在负环,存在就\( ...