实际上是改变了克隆出来对象String类型成员的指向不会影响被克隆对象的。
解释:如果原来对象的一个string变量进行初始化的时候指向的是一个字符串常量,该字符串常量会被放到常量池中
该string类型的引用将会指向该常量。进行克隆后得到一个新的对象,如果该对象的string变量重新赋值那么只会
有这个string 引用变量指向一个新的内存区域,对原来对象中的string变量不会有影响
实际上是改变了克隆出来对象String类型成员的指向不会影响被克隆对象的。
解释:如果原来对象的一个string变量进行初始化的时候指向的是一个字符串常量,该字符串常量会被放到常量池中
该string类型的引用将会指向该常量。进行克隆后得到一个新的对象,如果该对象的string变量重新赋值那么只会
有这个string 引用变量指向一个新的内存区域,对原来对象中的string变量不会有影响
想对一个对象进行处理又想保留原有的数据进行接下来的操作,就需要克隆了克隆分浅克隆和深克隆,浅克隆后的对象中非基本对象和原对象指向同一块内存因此對这些非基本对象的修改会同时更改克隆前后的对象。深克隆可以实现完全的克隆可以用反射的方式或序列化的方式实现。
为什么要使用克隆这其实反映嘚是一个很现实的问题,假如我们有一个对象:
java对象克隆底层使用C/C++实现的"="这个运算符,如果左右两边都是对象引用的话在java对象克隆中表示的将等号右边的引用赋值给等号左边的引用,二者指向的还是同一块内存所以任何一个引用对内存的操作都直接反映到另一个引用仩。
但是现在我想拿这个so0的数据进行一些操作,不想改变原来so0中的内容这时候就可以使用克隆了,它允许在堆中克隆出一块和原对象┅样的对象并将这个对象的地址赋予新的引用,这样显然我对新引用的操作,不会影响到原对象
当然,理解克隆最好还是对有比較好的理解。
还是那句话对于不熟悉的接口、方法,第一反应一定是查询JDK API
(1)此类实现了Cloneable接口,以指示Object的clone()方法可以合法地对该类实例進行按字段复制
(3)按照惯例实现此接口的类应该使用公共方法重写Object的clone()方法,Object的clone()方法是一个受保护的方法
创建并返回此对象的一个副本对于任何对象x,表达式:
把上面例子的main函数修改一下:
浅克隆(shallow clone)和深克隆(deep clone)反映的是当对象中还有对象的时候,那么:
1、浅克隆即很表层的克隆,如果我们要克隆对象只克隆它自身以及它所包含的所有对象的引用地址
2、深克隆,克隆除自身对象以外的所有对象包括自身所包含的所有对象实例
这两个概念应该很好理解,就不写代码了多提一句,所有的基本数据类型无论是浅克隆还是深克隆,都会进行原值克隆毕竟它们都不是对象,不是存储在堆中的
那其实Object的clone()方法,提供的是一种浅克隆的机制如果想要实现对对象的深克隆,在不引入第三方jar包的情况下可以使用两种办法:
1、先对对象进行序列化,紧接着马上反序列化出
2、先调用super.clone()方法克隆出一个新对象來然后在子类的clone()方法中手动给克隆出来的非基本数据类型(引用类型)赋值,比如ArrayList的clone()方法: