首页 > 分享 > java编程思想阅读笔记之对象克隆

java编程思想阅读笔记之对象克隆

普通的对象赋值例如:对象A=对象B,是指用不同的句柄指向同一个内存空间。

我们有时候需要进行深层复制,即指向不同的内存空间,可以实现接口:Cloneable

例一:

import java.util.*;

class MyObject implements Cloneable {

int i; 354

MyObject(int ii) { i = ii; }

public Object clone() {

Object o = null;

try {

o = super.clone();

} catch (CloneNotSupportedException e) {

System.out.println("MyObject can't clone");

}

return o;

}

public String toString() {

return Integer.toString(i);

}

}

public class LocalCopy {

static MyObject g(MyObject v) {

v.i++;

return v;

}

static MyObject f(MyObject v) {

v = (MyObject)v.clone();

v.i++;

return v;

}

public static void main(String[] args) {

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);

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

上述程序很简单,对象内只有普通数据成员。

例二:

public class Snake extends Object 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();

}

public String toString() {

String s = ":" + c;

if(next != null)

s += next.toString();

return s;

}

public Snake clone() {

Snake o = null;

try {

o = (Snake)super.clone();

} catch (CloneNotSupportedException e) {}

return o;

}

public static void main(String[] args) {

Snake s = new Snake(5, 'a');

System.out.println("s = " + s);

Snake s2 = s.clone();

System.out.println("s2 = " + s2);

s.increment();

System.out.println(

"after s.increment, s2 = " + s2);

}

}

 

一条Snake(蛇)由数段构成,每一段的类型都是Snake。所以,这是一个一段段链接起来的列表。所有段都是以循环方式创建的,每做好一段,都会使第一个构建器参数的值递减,直至最终为零。而为给每段赋予一个独一无二的标记,第二个参数(一个Char)的值在每次循环构建器调用时都会递增。 increment()方法的作用是循环递增每个标记,使我们能看到发生的变化;而 toString 则循环打印出每个标记。输出如下: 

  s = :a:b:c:d:e 
s2 = :a:b:c:d:e 
after s.increment, s2 = :a:c:d:e:f 

  这意味着只有第一段才是由Object.clone()复制的,所以此时进行的是一种“浅层复制”。若希望复制整条蛇——即进行“深层复制”——必须在被覆盖的clone()里采取附加的操作。 
通常可在从一个能克隆的类里调用 super.clone(),以确保所有基础类行动(包括Object.clone())能够进行。随着是为对象内每个句柄都明确调用一个 clone();否则那些句柄会别名变成原始对象的句柄。构建器的调用也大致相同——首先构造基础类,然后是下一个衍生的构建器……以此类推,直到位于最深层的衍生构建器。区别在于 clone()并不是个构建器,所以没有办法实现自动克隆。为了克隆,必须由自己明确进行。 

所以并不是深层复制:可以修改代码如下:

package com.myweb.Controller.test;

public class Snake extends Object 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();

}

public String toString() {

String s = ":" + c;

if(next != null)

s += next.toString();

return s;

}

public Snake clone() {

Snake o = null;

try {

o = (Snake)super.clone();

if(o.next!=null){

o.next=o.next.clone();

}

} catch (CloneNotSupportedException e) {}

return o;

}

public static void main(String[] args) {

Snake s = new Snake(5, 'a');

System.out.println("s = " + s);

Snake s2 = s.clone();

System.out.println("s2 = " + s2);

s.increment();

System.out.println(

"after s.increment, s2 = " + s2);

}

}

这边是深层复制了,注意克隆方法的内部实现有所不同。

最后再介绍一下关于vector的复制,其实差不多:

class Int2 implements Cloneable {

private int i;

public Int2(int ii) { i = ii; }

public void increment() { i++; }

public String toString() {

return Integer.toString(i);

}

public Object clone() {

Object o = null;

try {

o = super.clone();

} catch (CloneNotSupportedException e) {

System.out.println("Int2 can't clone");

}

return o;

}

}

class Int3 extends Int2 {

private int j;

public Int3(int i) { super(i);j=i; }

public void increment(){

j++;

}

public String toString(){

return Integer.toString(j);

}

}

public class AddingClone {

public static void main(String[] args) {

Int2 x = new Int2(10);

Int2 x2 = (Int2)x.clone();

x2.increment();

System.out.println(

"x = " + x + ", x2 = " + x2);

Int3 x3 = new Int3(7);

Int3 x4 = (Int3)x3.clone();

System.out.println(x3);

x3.increment();

System.out.println(x3);

System.out.println(x4);

Vector v = new Vector();

for(int i = 0; i < 10; i++ )

v.addElement(new Int2(i));

System.out.println("v: " + v);

Vector v2 = (Vector)v.clone();

for(int i = 0; i < v.size(); i++)

v2.setElementAt(

((Int2)v2.elementAt(i)).clone(), i);

for(Enumeration e = v.elements(); e.hasMoreElements(); )

((Int2)e.nextElement()).increment();

System.out.println("v: " + v);

System.out.println("v2: " + v2);

}

}

必须对对象内的对象进行一一克隆,有点递归的意思,才是深层复制。从上述代码还可以看出, Int3继承了Int2,Int2实现了public clone,Int3不用重复实现,输出如下:

x = 10, x2 = 11
7
8
7
v: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
v: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
v2: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

可能有错误,欢迎指出。顺便继续看看序列化实现深层复制。

相关知识

【JAVA】Java基础—面向对象编程:类与对象
JAVA编程艺术
Java对象生命周期管理:从创建到垃圾回收的完整解析
javascript dom 编程艺术pdf javascript dom编程艺术pdf下载网盘
JavaScript DOM 编程艺术 (第二版)学习之1
使用java编写一只玫瑰花
借花献佛!朋友干了5年整的Java面试官,给我分享了一份面试官最爱问的Java面试题
Java通用型支付+电商平台双系统实战
菜根花小宝贝
Java 并没有死!那么,Java这朵“永生花”是怎么永葆青春的呢?

网址: java编程思想阅读笔记之对象克隆 https://m.huajiangbk.com/newsview652475.html

所属分类:花卉
上一篇: 本周绘本推荐——《花婆婆》,清华
下一篇: NOIP2017初赛阅读程序写结