TOP

java clone()机制(一)
2014-11-24 07:25:33 】 浏览:10070
Tags:java clone 机制

Object的clone以及为什么如此实现
Object的clone的行为是最简单的。以堆上的内存存储解释的话(不计内务内存),对一个对象a的clone就是在堆上分配一个和a在堆上所占存储空间一样大的一块地方,然后把a的堆上内存的内容复制到这个新分配的内存空间上。

看例子。

class User {
	String name;
	int age;
}

class Account implements Cloneable {
	User user;
	long balance;

	@Override
	public Object clone() throws CloneNotSupportedException {
		return super.clone();
	}
}

		// user.
		User user = new User();
		user.name = "user";
		user.age = 20;
		// account.
		Account account = new Account();
		account.user = user;
		account.balance = 10000;
		// copy.
		Account copy = (Account) account.clone();

		// balance因为是primitive,所以copy和原型是相等且独立的。
		Assert.assertEquals(copy.balance, account.balance);
		copy.balance = 20000;
		// 改变copy不影响原型。
		Assert.assertTrue(copy.balance != account.balance);

		// user因为是引用类型,所以copy和原型的引用是同一的。
		Assert.assertTrue(copy.user == account.user);
		copy.user.name = "newName";
		// 改变的是同一个东西。
		Assert.assertEquals("newName", account.user.name);

vcHLz+C1yMfSuPTA66GjIDxicj4K0v3Tw8Dg0M299r32yse4tNbGwcvSu8/C0v3Tw6OsY29webrN1K3QzdL908O1xLarzvfKx9K70fm1xKGjIDxicj4K1eK49r7NysfL+c69tcTHs2NvcHnBy6GjIDxicj4K0qrKtc/Wye5jb3B5o6y8tLi01sbUrdDN1tC21M/ztcTE2rTmY29weaOstviyu732vfbKx9K7uPbS/dPDoaPWu9PQ19S8uravytbBy6GjIDxicj4Ktci1yKOsyseyu8rHy/nT0LXE0v3Tw8Dg0M22vNDo0qrJ7mNvcHnE2KO/IDxicj4KsrvKx6OhIDxicj4KztLDx9auy/nS1NKqye5jb3B5o6zKx9LyzqrErMjPtcTKtc/WzOG5qbXEx7Njb3B5srvKx7j0wOu1xKOsu7vR1Nauo6y4xLHkY29webXEtqvO96Osu+HTsM/stb3UrdDNtcTE2rK/oaOxyMjnwP3X09bQo6y4xLHkY29webXEdXNlcrXEbmFtZaOs07DP7MHL1K3QzaGjIDxicj4KyOe5+87Sw8fSqmNvcHm1xMDgyseyu7/JseS1xMTYo6zI51N0cmluZ6Osw7vT0Le9t6i/ydLUuMSx5Mv8tcTE2rK/17TMrMTYoaMgPGJyPgo8L3A+CjxwPjxwcmUgY2xhc3M9"brush:java;">class User implements Cloneable { String name; int age; @Override public Object clone() throws CloneNotSupportedException { return super.clone(); } }
		// user.
		User user = new User();
		user.name = "user";
		user.age = 20;

		// copy
		User copy = (User) user.clone();

		// age因为是primitive,所以copy和原型是相等且独立的。
		Assert.assertEquals(copy.age, user.age);
		copy.age = 30;
		// 改变copy不影响原型。
		Assert.assertTrue(copy.age != user.age);

		// name因为是引用类型,所以copy和原型的引用是同一的。
		Assert.assertTrue(copy.name == user.name);
		// String为不可变类。没有办法可以通过对copy.name的字符串的操作改变这个字符串。
		// 改变引用新的对象不会影响原型。
		copy.name = "newname";
		Assert.assertEquals("newname", copy.name);
		Assert.assertEquals("user", user.name);

可见,在考虑clone时,primitive和不可变对象类型是可以同等对待的。

java为什么如此实现clone呢?
也许有以下考虑。
1 效率和简单性,简单的copy一个对象在堆上的的内存比遍历一个对象网然后内存深copy明显效率高并且简单。
2 不给别的类强加意义。如果A实现了Cloneable,同时有一个引用指向B,如果直接复制内存进行深copy的话,意味着B在意义上也是支持Clone的,但是这个是在使用B的A中做的,B甚至都不知道。破坏了B原有的接口。
3 有可能破坏语义。如果A实现了Cloneable,同时有一个引用指向B,该B实现为单例模式,如果直接复制内存进行深copy的话,破坏了B的单例模式。
4 方便且更灵活,如果A引用一个不可变对象,则内存deep copy是一种浪费。Shadow copy给了程序员更好的灵活性。

如何clone
clone三部曲。
1 声明实现Cloneable接口。
2 调用super.clone拿到一个对象,如果父类的clone实现没有问题的话,在该对象的内存存储中,所有父类定义的field都已经clone好了,该类中的primitive和不可变类型引用也克隆好了,可变类型引用都是浅copy。
3 把浅copy的引用指向原型对象新的克隆体。
给个例子。

class User implements Cloneable {
	String name;
	int age;

	@Override
	public User clone() throws CloneNotSupportedException {
		return (User) super.clone();
	}
}

class Account implements Cloneable {
	User user;
	long  
		
java clone()机制(一) https://www.cppentry.com/bencandy.php?fid=76&id=43617

首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇字符串处理,替换忽略大小写,空格 下一篇HibernateCRUD基础框架(2)-HQL语..