拷贝对象要细心
url: http://lsy.javaeye.com/blog/46189
在说对象的拷贝问题之前,先提一下java对参数的传递。在Java语言中通过值传递
机制将所有实参的值传递给方法,这就意味着方法将接受所有实参
的一个拷贝,看下面的代码:
-
public
static
void
main(String[]args){
-
int
i=1
;
-
int
j=2
;
- change(i,j);
- System.out.println(i+j);
- }
-
public
static
void
change(int
i,int
j){
- i+=10
;
- j+=10
;
- }
public static void main(String[] args) {
int i = 1;
int j = 2;
change(i,j);
System.out.println(i+j);
}
public static void change(int i, int j){
i += 10;
j += 10;
}
打印结果是3,并不会影响到原来的变量值。但是如果方法接受的实参类型不是基本类型的变量,而是对象,那么Java语言运用的机制就是引用传递
。继续看代码:
先定义两个Dog类:
-
public
class
Flea{
-
private
Stringsize;
-
public
Flea(Stringsize){
-
this
.size=size;
- }
- }
-
public
class
Dog{
-
private
Stringname;
-
private
int
age;
-
private
Fleaflea;
-
public
Dog(StringaName,int
age){
-
this
.name=aName;
-
this
.age=age;
-
this
.flea=new
Flea("small"
);
- }
-
public
StringtoString(){
-
return
"Dogageis"
+age+"!Dog'sfleasizeis"
+flea.getSize();
- }
- }
public class Flea{
private String size;
public Flea(String size) {
this.size = size;
}
}
public class Dog {
private String name;
private int age;
private Flea flea;
public Dog(String aName,int age) {
this.name = aName;
this.age = age;
this.flea = new Flea("small");
}
public String toString(){
return "Dog age is "+age+"! Dog's flea size is "+flea.getSize();
}
}
接着
-
public
static
void
main(String[]args){
- Dogdog=new
Dog("Tom"
,10
);
- change(dog);
- System.out.println(dog);
- }
-
public
static
void
change(Dogdog){
- dog.setAge(100
);
- dog.getFlea().setSize("big"
);
- }
public static void main(String[] args) {
Dog dog = new Dog("Tom",10);
change(dog);
System.out.println(dog);
}
public static void change(Dog dog){
dog.setAge(100);
dog.getFlea().setSize("big");
}
打印结果应该是Dog age is 100 ! Dog's flea size is big。这是因为传递给方法的变量是一个对象引用的副本,也就是说dog是一个对象的引用,而传递给方法的是dog这个引用的副本,因此二者引用的是同一个对象,因此在方法中对象改变了,那么方法外对象也会改变。这是要做的事情就是在对象传递给方法之前先做拷贝。因此修改一下Dog.java
-
public
class
Fleaimplements
Cloneable{
-
private
Stringsize;
-
public
Flea(Stringsize){
-
this
.size=size;
- }
-
public
Objectclone(){
- FleanewFlea=null
;
-
try
{
- newFlea=super
.clone();
- }
-
catch
(CloneNotSupportedExceptione){}
-
return
newFlea;
- }
- }
-
public
class
Dogimplements
Cloneable{
-
private
Stringname;
-
private
int
age;
-
public
Dog(StringaName,int
age){
-
this
.name=aName;
-
this
.age=age;
-
this
.flea=new
Flea("small"
);
- }
-
public
Objectclone(){
- DognewDog=null
;
-
try
{
- newDog=super
.clone();
- }
-
catch
(CloneNotSupportedExceptione){}
-
return
newDog;
- }
-
public
StringtoString(){
-
return
"Dogageis"
+age+"!Dog'sfleasizeis"
+flea.getSize();
- }
- }
public class Flea implements Cloneable {
private String size;
public Flea(String size) {
this.size = size;
}
public Object clone() {
Flea newFlea = null;
try{
newFlea = super.clone();
}
catch(CloneNotSupportedException e){}
return newFlea;
}
}
public class Dog implements Cloneable{
private String name;
private int age;
public Dog(String aName, int age) {
this.name = aName;
this.age = age;
this.flea = new Flea("small");
}
public Object clone() {
Dog newDog = null;
try{
newDog = super.clone();
}
catch(CloneNotSupportedException e){}
return newDog;
}
public String toString(){
return "Dog age is "+age+"! Dog's flea size is "+flea.getSize();
}
}
接下来调整一下测试代码:
-
public
static
void
main(String[]args){
- Dogdog=new
Dog("Tom"
,10
);
- DogcDog=(Dog)dog.clone();
- change(dog);
- System.out.println(dog);
- System.out.println(cDog);
- }
public static void main(String[] args) {
Dog dog = new Dog("Tom",10);
Dog cDog = (Dog)dog.clone();
change(dog);
System.out.println(dog);
System.out.println(cDog);
}
可以看到打印结果是:
Dog age is 100! Dog's flea size is big
Dog age is 10! Dog's flea size is big
这时结果仍然不能让人满意,因为虽然Dog的age被保留了下来,但是Dog的Flea的size确仍然被改变了。这就是需要注意的地方,拷贝对象时留意对象的嵌套对象的拷贝,如此修改一下Dog的clone方法:
-
public
Objectclone(){
- DognewDog=null
;
-
try
{
-
newDog=(Dog)super
.clone();
-
newDog.flea=(Flea)flea.clone();
- }
-
catch
(CloneNotSupportedExceptione){}
-
return
newDog;
- }
public Object clone() {
Dog newDog = null;
try{
newDog = (Dog)super.clone();
newDog.flea = (Flea)flea.clone();//加上这一行
}
catch(CloneNotSupportedException e){}
return newDog;
}
再次运行一次,可以看到结果是:
Dog age is 100! Dog's flea size is big
Dog age is 10! Dog's flea size is small
这样就可以保留在调用方法之前的对象了。^_^
java中的clone机制
http://blog.csdn.net/hdy007/archive/2007/03/01/1518300.aspx
java中有两种clone方式,一种是浅拷贝,一种是深拷贝.
Object 定义了clone方法,而且定义为protected保护型,返回Object.
如果你要使自定义的类能够被clone,就必须实现Cloneable接口并且
重写clone()方法.
class CloneTest1() implements Cloneable
{
java.util.Date date;
public Object clone()
{
try {
return super.clone();
}
catch (CloneNotSupportedException ex) {
//如果没有实现Cloneable接口,抛出异常
return null;
}
}
}
CloneTest1简单的实现了Clone()方法,只是简单的调用Object的clone()方法.
这种方式属于浅拷贝,只是clone了CloneTest1的表层.测试如下:
CloneTest1 src=new CloneTest1();
CloneTest1 des=(CloneTest1)src.clone();
System.out.println(src==des); //false 说明有两个CloneTest1的实例.
System.out.println(src.date==des.date); //true 指向相同的数据成员.
有时候我们需要一个完全的备份,就是深层次的拷贝
class CloneTest2 implements Cloneable{
java.util.Date date;
public Object clone(){
try {
CloneTest2 ct=(CloneTest2)super.Clone();
ct.date=date.clone();
return ct;
}
catch (CloneNotSupportedException ex) {
return null;
}
}
}
上面的实现就是一个深拷贝了,要实现深拷贝类中的数据成员都得是Cloneable的(当然
你也可以不是,那就是自找麻烦):
class NotCloneable{
public String str;
}
class CloneTest3{
NotCloneable nc;
public clone(){
try
{
CloneTest3 ct=(CloneTest3)super.clone();
ct.nc=new NotCloneable();
ct.nc.str=str;
return ct;
}
catch (CloneNotSupportedException ex) {
return null;
}
}
}
这样虽然也实现了深拷贝,但是非常不好.
url: http://onlylove.javaeye.com/blog/265113
1,什么是Clone ?
简单地说, Clone
就是对于给定的一个对象实例 o
,得到另一个对象实例 o’
: o
与 o’
类
型相同( o.getClass() == o’.getClass()
),内容相同(对于 o/o’
中的字段 f
,如果 f
是基本数据类型,则 o.f == o’.f
;如果
f
是对象引用,则 o.f ==
o’.f
或 o.f
指向的对象与 o’.f
指向的对象的内容相同)。通常称 o’
为 o
的克隆或副本。
2,什么时候使用Clone?
当需要修改对象属性,又不想影响原来的属性值,这时候就应该使用clone了。
3,
Java
对 clone
的支持
万类之初的 Object 类有 clone() 方法:
protected native Object
clone() throws CloneNotSupportedException;
该方法是 protected 的,显然是留待被子类 override
的。该方法又是 native 的,必然做了
与具体平台相关的底层工作。
事实上,类 Object 的 clone() 方法首先会检查
this.getClass() 是否实现了 Cloneable 接口。
Cloneable
只是一个标志接口而已,用来标志该类是否有克隆功能。
public interface Cloneable {
}
如果
this.getClass() 没有实现 Cloneable 接口, clone() 就会抛 CloneNotSupportedException
返回
。否则就会创建一个类型为 this.getClass() 的对象 other ,并将 this 各 field 的值赋值给 other 的对应 field
,然后返回 other 。
如此一来,我们要定义一个具有 Clone 功能的类就相当方便:
1. 在类的声明中加入“
implements Cloneable ”,标志该类有克隆功能;
2. Override 类 Object 的 clone()
方法,在该方法中调用 super.clone() :
4,shallow clone and deep clone
Clone是如何完成的呢?Object在对某个对象实施Clone时对其是一无所知的,它仅仅是简单地执行域对域的copy,这就是Shallow
Clone。Java Collection
类库中具体数据结构类( ArrayList/LinkedList
, HashSet/TreeSet
, HashMap/TreeMap
等)都具有克隆功能,且都是 Shallow Clone。在有种情况下,这种shallow
Clone就会问题,这个情况就是当,要clone的对象中的某个属性是一个引用,
这样克隆类就和原始类共享了一部分信息,对这个属性操作就会影响原始类,所以就需要deep clone.
举例见:http://onlylove.javaeye.com/blog/265113
分享到:
相关推荐
Java中的clone方法详解_动力节点Java学院,动力节点口口相传的Java黄埔军校
用 Java 语言编写的 初学者可学习的clone()
详细的描述了Java中 clone方法使用
java中clone的详细用法,分浅拷贝和深拷贝,并分别有详细的实例介绍。从原理分析。
主要介绍了 Java clone方法详解及简单实例的相关资料,需要的朋友可以参考下
对java clone的一些讲解,以及我个人的一些心得等等,
现在Clone已经不是一个新鲜词语了,伴随着“多莉”的产生这个词语确实很“火”过一阵子,在java中也有这么一个概念,它可以让我们很方便的“制造”出一个对象的副本来,下面来具体看看java中的Clone机制是如何工作的...
Java Clone(类的复制)实例代码 Java Clone(类的复制)实例代码
Java深浅clone测试代码 流拷贝 Cloneable
Clone 属性的相关内容 Clone 属性的相关内容
Java中的克隆(Clone)机制,很少涉及的内容。
clone顾名思义就是复制, 在Java语言中, clone方法被对象调用,所以会复制对象。下面通过本文给大家介绍java中的clone方法,感兴趣的朋友一起看看吧
java code clone
clone的用法 希望有帮助,仅供参考 通过例子的分析,可以对克隆的方法有所深入了解
java中clone的详细用法,分浅拷贝和深拷贝,并分别有详细的实例介绍。从原理分析。
javascript中clone对象详解.docx
clone顾名思义是复制, 在Java语言中, clone方法被对象调用,所以会复制对象。所谓的复制对象,首先要分配一个和源对象同样大小的空间,在这个空间中创建一个新的对象。那么在java语言中,有几种方式可以创建...
今天小编就为大家分享一篇关于Java Clone深拷贝与浅拷贝的两种实现方法,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
主要介绍了java 中clone()的使用方法的相关资料,希望通过本文能帮助大家能掌握clone()的克隆方法,需要的朋友可以参考下