`
zhang_xzhi_xjtu
  • 浏览: 536316 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

深入理解java的clone

    博客分类:
  • java
阅读更多
目录

预备知识
为什么要clone
Object的clone以及为什么如此实现
如何clone
对clone的态度
其他的选择
和Serializable的比较
性能

预备知识

为了理解java的clone,有必要先温习以下的知识。
java的类型,java的类型分为两大类,一类为primitive,如int,另一类为引用类型,如String,Object等等。
java引用类型的存储,java的引用类型都是存储在堆上的。
public class B {
	int a;
	String b;

	public B(int a, String b) {
		super();
		this.a = a;
		this.b = b;
	}
}

对这样一个引用类型的实例,我们可以推测,在堆上它的内存存储形式(除去指向class的引用,锁的管理等等内务事务所占内存),应该有一个int值表示a,以及一个引用,该引用指向b在堆上的存储空间。


为什么要clone

恩,因为需要。废话。
有名的GoF设计模式里有一个模式为原型模式,用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象.
简单的说就是clone一个对象实例。使得clone出来的copy和原有的对象一模一样。

插一个简单使用clone的例子,如果一个对象内部有可变对象实例的话,public API不应该直接返回该对象的引用,以防调用方的code改变该对象的内部状态。这个时候可以返回该对象的clone。

问题来了,什么叫一模一样。
一般来说,有
x.clone() != x
x.clone().getClass() == x.getClass()
x.clone().equals(x)
但是这些都不是强制的。
我们需要什么样的clone就搞出什么样的clone好了。
一般而言,我们要的clone应该是这样的。copy和原型的内容一样,但是又是彼此隔离的。即在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);



恩,默认实现是帮了我们一些忙,但是不是全部。
primitive的确做到了相等且隔离。
引用类型仅仅是复制了一下引用,copy和原型引用的东西是一样的。
这个就是所谓的浅copy了。
要实现深copy,即复制原型中对象的内存copy,而不仅仅是一个引用。只有自己动手了。
等等,是不是所有的引用类型都需要深copy呢?
不是!
我们之所以要深copy,是因为默认的实现提供的浅copy不是隔离的,换言之,改变copy的东西,会影响到原型的内部。比如例子中,改变copy的user的name,影响了原型。
如果我们要copy的类是不可变的呢,如String,没有方法可以改变它的内部状态呢。
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 balance;

	@Override
	public Account clone() throws CloneNotSupportedException {
		Account account = null;

		account = (Account) super.clone();
		if (user != null) {
			account.user = user.clone();
		}

		return account;
	}
}




对clone的态度

clone嘛,我觉得是个好东西,毕竟系统默认实现已经帮我们做了很多事情了。
但是它也是有缺点的。
1 手工维护clone的调用链。这个问题不大,程序员有责任做好。
2 如果class的field是个final的可变类,就不行了。三部曲的第三步没有办法做了。

考虑一个类对clone的态度,有如下几种。
1 公开支持:好吧,按照clone三部曲实现吧。前提是父类支持(公开或者默默)。
2 默默支持:不实现Cloneable接口,但是在类里面有正确的protected的clone实现,这样,该类不支持clone,但是它的子类如果想支持的话也不妨碍。
3 不支持:好吧,为了明确该目的,提供一个抛CloneNotSupportedException 异常的protected的clone实现。
4 看情况支持:该类内部可以保存其他类的实例,如果其他类支持则该类支持,如果其他类不支持,该类没有办法,只有不支持。


其他的选择

可以用原型构造函数,或者静态copy方法来手工制作一个对象的copy。
好处是即使class的field为final,也不会影响该方法的使用。不好的地方是所有的primitive赋值都得自己维护。


和Serializable的比较

使用Serializable同样可以做到对象的clone。但是:
Cloneable本身就是为clone设计的,虽然有一些缺点,但是如果它可以clone的话无疑用它来做clone比较合适。如果不行的话用原型构造函数,或者静态copy方法也可以。

Serializable制作clone的话,添加了太多其它的东西,增加了复杂性。
1 所有的相关的类都得支持Serializable。这个相比支持Cloneable只会工作量更大
2 Serializable添加了更多的意义,除了提供一个方法用Serializable制作Clone,该类等于也添加了其它的public API,如果一个类实现了Serializable,等于它的2进制形式就已经是其API的一部分了,不便于该类以后内部的改动。
3 当类用Serializable来实现clone时,用户如果保存了一个老版本的对象2进制,该类升级,用户用新版本的类反系列化该对象,再调用该对象用Serializable实现的clone。这里为了一个clone的方法又引入了类版本兼容性的问题。不划算。


性能

不可否认,JVM越来越快了。
但是系统默认的native实现还是挺快的。
clone一个有100个元素的int数组,用系统默认的clone比静态copy方法快2倍左右。
  • 大小: 8.2 KB
  • 大小: 14.5 KB
  • 大小: 23.7 KB
分享到:
评论
34 楼 在世界的中心呼喚愛 2015-03-06  
时隔1.5年,再看了楼主finalize 文章,终于看懂。
这clone我觉得还是理解下他的思想就行,apache就有bean复制的功能了。效率也不低,也不需要覆写方法clone方法.
我没有跟踪过apache的bean复制源码,不知道是深复制,还是浅复制..
33 楼 zhang_xzhi_xjtu 2014-03-26  
madison2 写道
写的好详细呀。。 

过奖
32 楼 madison2 2014-03-26  
写的好详细呀。。 
31 楼 agapple 2010-08-19  
to 楼主:

性能

不可否认,JVM越来越快了。
但是系统默认的native实现还是挺快的。
clone一个有100个元素的int数组,用系统默认的clone比静态copy方法快2倍左右。

------------------------------------------------------------------

针对这个我做了下测试。
iint fortimes = 1000 * 100;
        int n = 10000;
        int[] ints = new int[n];
        for (int i = 0; i < n; i++) {
            ints[i] = i;
        }

        long start = System.currentTimeMillis();
        for (int i = 0; i < fortimes; i++) {
            ints.clone();
        }
        System.out.println("clone cost: " + (System.currentTimeMillis() - start));

        start = System.currentTimeMillis();
        int[] intsCopy = new int[n];
        for (int i = 0; i < fortimes; i++) {
            System.arraycopy(ints, 0, intsCopy, 0, ints.length);
        }
        System.out.println("copy cost: " + (System.currentTimeMillis() - start));

        start = System.currentTimeMillis();
        int[] intsfor = new int[n];
        for (int i = 0; i < fortimes; i++) {
            int length = ints.length;
            for (int j = 0; j < length; j++) {
                intsfor[j] = ints[j];
            }
        }
        System.out.println("for copy cost: " + (System.currentTimeMillis() - start));


发现性能没你说的那么好,发现还不如我循环copy来得快。
clone cost: 2698 ms
copy cost: 480 ms
for copy cost: 496 ms


针对String对象的我也做了类似测试,发现效果也没系统的system.arraycopy来的好
clone cost: 2636
copy cost: 523
for copy cost: 2882


不知道LZ的2倍性能提升是咋来的,做了特殊优化?
30 楼 zhang_xzhi_xjtu 2010-08-19  
谢谢大家的评论
29 楼 lixia0417 2010-08-19  
真是不错,楼主把这个clone讲得真详细啊;
28 楼 kevin850115 2010-02-28  
zhang_xzhi_xjtu 写道
目录

预备知识
为什么要clone
Object的clone以及为什么如此实现
如何clone
对clone的态度
其他的选择
和Serializable的比较
性能

预备知识

为了理解java的clone,有必要先温习以下的知识。
java的类型,java的类型分为两大类,一类为primitive,如int,另一类为引用类型,如String,Object等等。
java引用类型的存储,java的引用类型都是存储在堆上的。
public class B {
	int a;
	String b;

	public B(int a, String b) {
		super();
		this.a = a;
		this.b = b;
	}
}

对这样一个引用类型的实例,我们可以推测,在堆上它的内存存储形式(除去指向class的引用,锁的管理等等内务事务所占内存),应该有一个int值表示a,以及一个引用,该引用指向b在堆上的存储空间。


为什么要clone

恩,因为需要。废话。
有名的GoF设计模式里有一个模式为原型模式,用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象.
简单的说就是clone一个对象实例。使得clone出来的copy和原有的对象一模一样。

插一个简单使用clone的例子,如果一个对象内部有可变对象实例的话,public API不应该直接返回该对象的引用,以防调用方的code改变该对象的内部状态。这个时候可以返回该对象的clone。

问题来了,什么叫一模一样。
一般来说,有
x.clone() != x
x.clone().getClass() == x.getClass()
x.clone().equals(x)
但是这些都不是强制的。
我们需要什么样的clone就搞出什么样的clone好了。
一般而言,我们要的clone应该是这样的。copy和原型的内容一样,但是又是彼此隔离的。即在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);



恩,默认实现是帮了我们一些忙,但是不是全部。
primitive的确做到了相等且隔离。
引用类型仅仅是复制了一下引用,copy和原型引用的东西是一样的。
这个就是所谓的浅copy了。
要实现深copy,即复制原型中对象的内存copy,而不仅仅是一个引用。只有自己动手了。
等等,是不是所有的引用类型都需要深copy呢?
不是!
我们之所以要深copy,是因为默认的实现提供的浅copy不是隔离的,换言之,改变copy的东西,会影响到原型的内部。比如例子中,改变copy的user的name,影响了原型。
如果我们要copy的类是不可变的呢,如String,没有方法可以改变它的内部状态呢。
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 balance;

	@Override
	public Account clone() throws CloneNotSupportedException {
		Account account = null;

		account = (Account) super.clone();
		if (user != null) {
			account.user = user.clone();
		}

		return account;
	}
}




对clone的态度

clone嘛,我觉得是个好东西,毕竟系统默认实现已经帮我们做了很多事情了。
但是它也是有缺点的。
1 手工维护clone的调用链。这个问题不大,程序员有责任做好。
2 如果class的field是个final的可变类,就不行了。三部曲的第三步没有办法做了。

考虑一个类对clone的态度,有如下几种。
1 公开支持:好吧,按照clone三部曲实现吧。前提是父类支持(公开或者默默)。
2 默默支持:不实现Cloneable接口,但是在类里面有正确的protected的clone实现,这样,该类不支持clone,但是它的子类如果想支持的话也不妨碍。
3 不支持:好吧,为了明确该目的,提供一个抛CloneNotSupportedException 异常的protected的clone实现。
4 看情况支持:该类内部可以保存其他类的实例,如果其他类支持则该类支持,如果其他类不支持,该类没有办法,只有不支持。


其他的选择

可以用原型构造函数,或者静态copy方法来手工制作一个对象的copy。
好处是即使class的field为final,也不会影响该方法的使用。不好的地方是所有的primitive赋值都得自己维护。


和Serializable的比较

使用Serializable同样可以做到对象的clone。但是:
Cloneable本身就是为clone设计的,虽然有一些缺点,但是如果它可以clone的话无疑用它来做clone比较合适。如果不行的话用原型构造函数,或者静态copy方法也可以。

Serializable制作clone的话,添加了太多其它的东西,增加了复杂性。
1 所有的相关的类都得支持Serializable。这个相比支持Cloneable只会工作量更大
2 Serializable添加了更多的意义,除了提供一个方法用Serializable制作Clone,该类等于也添加了其它的public API,如果一个类实现了Serializable,等于它的2进制形式就已经是其API的一部分了,不便于该类以后内部的改动。
3 当类用Serializable来实现clone时,用户如果保存了一个老版本的对象2进制,该类升级,用户用新版本的类反系列化该对象,再调用该对象用Serializable实现的clone。这里为了一个clone的方法又引入了类版本兼容性的问题。不划算。


性能

不可否认,JVM越来越快了。
但是系统默认的native实现还是挺快的。
clone一个有100个元素的int数组,用系统默认的clone比静态copy方法快2倍左右。

27 楼 zhang_xzhi_xjtu 2009-11-27  
恩 同意 但是不知道大家对什么感兴趣 我本来是想写深入系列的
现在有深入clone,深入finalize,还有一个ref的发到blog上了
26 楼 itstarting 2009-11-26  
有些基础的东西,仔细深抠也蛮有味道的
如果大家能策划个这样的专题的话,大家的基础会越来越扎实
25 楼 yangtse_ye 2009-11-25  
小知识点大学问
24 楼 段箭*残箫 2009-10-14  
分析的相当的好!~ [flash=200,200][/flash]
23 楼 zhang_xzhi_xjtu 2009-10-13  
luojiaxu_adames 写道
也就是说:要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给了程序员更好的灵活性。
22 楼 luojiaxu_adames 2009-10-13  
也就是说:要clone的类中:原始类型是可以复制的,引用类只是传了个引用,并没有把对象传过去。
那他们为什么这么做呢!
21 楼 madbluesky 2009-10-12  
恩,原型模式的深copy比较舒服
20 楼 zhang_xzhi_xjtu 2009-10-11  
unsid 写道
我记得某大师说过,clone是java里相对比较没用的特性之一,这位大师说在他写java10多年的历史上,用到clone不超过5次,而且几乎都有可替代的解决方法。你能设想一个必须使用clone解决问题或者不使用clone就要绕很大弯路才能实现的场景么?


大师说的话不能全信,因为很多大师说的话都是矛盾的。
基本上任何方法都会有替代的方案的。
clone不止是Cloneable接口而已,而是一个机制,背后的思想是原型模式。
当Cloneable适用于要clone的类时,选择Cloneable本身还是比较简单的,当有其它限制时,考虑copy构造函数或者静态copy方法或者其它方案。
19 楼 zhang_xzhi_xjtu 2009-10-11  
galaxystar 写道
如果不考虑性能的话,深copy用serialization是比较简单,有效的做法。


我在主贴里更新了和serialization的比较。
18 楼 unsid 2009-10-11  
我记得某大师说过,clone是java里相对比较没用的特性之一,这位大师说在他写java10多年的历史上,用到clone不超过5次,而且几乎都有可替代的解决方法。你能设想一个必须使用clone解决问题或者不使用clone就要绕很大弯路才能实现的场景么?
17 楼 galaxystar 2009-10-11  
ideal46 写道
galaxystar 写道
如果不考虑性能的话,深copy用serialization是比较简单,有效的做法。

两者有什么区别与联系?

你可以参考下这篇文章所述:
http://weblogs.java.net/blog/emcmanus/archive/2007/04/cloning_java_ob.html
16 楼 ideal46 2009-10-11  
galaxystar 写道
如果不考虑性能的话,深copy用serialization是比较简单,有效的做法。

两者有什么区别与联系?
15 楼 ideal46 2009-10-11  
分析的很有道理,我想请教一下  serilization方式的克隆跟 结构化类克隆有什么区别?

相关推荐

    java clone的小例子

    这个小例子将帮助初学者理解如何在Java中使用`clone()`来创建对象的副本。让我们深入探讨`clone()`方法以及它在实际编程中的应用。 首先,`clone()`方法是Java Object类的一个成员方法,这意味着所有Java类都隐式地...

    java_clone用法

    在深入了解`clone`之前,我们需要了解几个基础概念: 1. **Java的类型**:Java中的数据类型主要分为两大类——原始类型(如`int`)和引用类型(如`String`, `Object`等)。 2. **引用类型的存储**:所有引用类型的...

    java clone

    本文将深入探讨Java中的`clone`方法,包括其工作原理、使用场景、注意事项以及一些个人实践心得。 首先,让我们理解什么是`clone`。在Java中,`clone`方法主要用于创建一个现有对象的副本,这个副本与原始对象具有...

    Java深浅clone

    在本文中,我们将深入探讨Java中的浅克隆(shallow clone)和深克隆(deep clone),并结合测试代码进行分析。 首先,让我们理解`Cloneable`接口。在Java中,如果一个类想要支持`clone()`方法,它必须实现`...

    关于java clone的一些基本的概念

    本文将深入探讨Java中的`clone`方法及其相关知识点。 首先,`clone`方法是Java `Object`类的一个成员方法,定义为`protected Object clone() throws CloneNotSupportedException`。这意味着所有Java类都隐式地继承...

    java中的指针,引用及对象的clone

    ### Java中的指针概念与引用解析 #### 一、引言 Java作为一种广泛使用的面向对象编程语言,在设计之初就摒弃了C/C++中的指针...通过深入理解这些概念,开发者可以更好地利用Java的强大功能来构建高质量的应用程序。

    Java中clone方法共6页.pdf.zip

    在Java编程语言中,`clone()`方法是一个非常重要的概念,特别是在对象复制和克隆方面。这个方法来源于`java.lang.Object`...深入理解这些概念对于提升Java编程技能至关重要,特别是涉及到对象复制和数据安全的项目中。

    如何通过JVM角度谈谈Java的clone操作

    本文将从JVM的角度深入探讨Java的`clone`操作,揭示其工作原理及其潜在的问题。 首先,让我们理解`clone`方法的工作机制。在Java中,`clone`方法是`Object`类的一个受保护的方法,这意味着所有Java对象都隐含地继承...

    深入理解Java中的克隆

    在Java中,克隆是通过`Object`类的`clone()`方法实现的,但使用克隆时有一些特定的要求和限制。 首先,为了能够克隆一个对象,该对象所在的类必须实现`Cloneable`接口。`Cloneable`接口是个特殊的标识接口,它没有...

    深入理解java中的拷贝机制

    本篇文章将深入探讨这两种拷贝机制,特别是如何在Java中实现它们。 首先,浅拷贝是创建一个新对象,其引用的数据成员仍然是对原对象数据成员的引用。这意味着,如果原对象的数据成员是引用类型,修改副本对象的这些...

    java object 之clone方法全面解析

    这篇文章将深入探讨`clone()`方法的工作原理、使用场景以及浅拷贝(shallow clone)与深拷贝(deep clone)的区别。 首先,让我们了解`clone()`方法的定义: ```java protected native Object clone() throws ...

    clone()方法示例(对象克隆)_对象克隆_nervouse78_源码

    总的来说,`clone()`方法是Java中一种快速创建对象副本的手段,但它需要开发者对浅拷贝和深拷贝有清晰的理解,并根据实际需求适当地处理对象的属性。通过`nervouse78`的示例,你可以学习到如何在实际项目中运用`...

    Java基础入门一.pdf

    《Java编程思想》提供了关于对象入门、类继承以及接口等基础和高级特性的讲解,而《深入理解Java虚拟机》则深入讲解了垃圾收集器、内存分配策略以及JVM内部的工作机制。 Spring框架是Java企业级应用开发中最重要的...

    Java深复制与浅复制&Clone

    在Java编程语言中,对象复制是一个常见的操作,...理解并正确使用浅复制和深复制对于开发高效、健壮的Java应用程序至关重要。在处理复杂的数据结构时,应根据需求选择合适的复制策略,以避免不必要的副作用和数据污染。

    详解java中的深拷贝和浅拷贝(clone()方法的重写、使用序列化实现真正的深拷贝)

    本文将深入探讨这两种拷贝方式,并着重讲解如何通过重写`clone()`方法以及使用序列化来实现深拷贝。 1. 浅拷贝: 浅拷贝是指创建一个新对象,该对象拥有原始对象的引用字段的副本。这意味着如果原始对象的字段包含...

    JAVA面试宝典.pdf

    第二章深入讲解JavaSE基础,这部分主要围绕Java的面向对象特性展开,如封装、继承、多态等概念。访问权限修饰符public、private、protected以及默认权限的理解是基础中的关键,它们决定了类和成员的可见性。clone...

    darts-clone-java-master.zip_DARTS代码_darts

    在本压缩包"Darts-Clone-Java-Master.zip"中,包含了Java实现的DARTS算法源代码,非常适合初学者深入理解和实践时间序列分析。 DARTS的核心思想是通过自回归模型(AR,AutoRegressive)来预测未来的值,其中每个...

Global site tag (gtag.js) - Google Analytics