对象数组深拷贝不行

时间:2022-12-25 19:52:57
看看这段代码哪里有问题?深拷贝没有成功。


class ArrayTest
{
public static void main(String[] args)
{
Point[] pt1=new Point[]{new Point(1,1),new Point(3,3),new Point(2,2)};
Point[] pt2=(Point[])pt1.clone();
System.out.println(pt1==pt2); //输出false了,好像不是引用了同一个堆内存
pt2[1].x=5;
pt2[1].y=5;
System.out.println(pt1[1].x+","+pt1[1].y); //pt1的xy坐标受到了影响,不知何解?
}
}

class Point implements Cloneable
{
int x,y;
Point(int x,int y)
{
this.x=x;
this.y=y;
}

public Object clone()
{
Object o=null;
try
{
o=super.clone();
}
catch(CloneNotSupportedException e)
{
System.out.println(e.toString());
}
return o;
}
}

12 个解决方案

#1


你的那个Point 的clone方法根本不会执行。

#2


Point[] pt2=(Point[])pt1.clone();,clone()调用的是数据对象pt1的方法,而不是类Point创建的clone方法.

#3


Point[] pt2=(Point[])pt1.clone();,clone()调用的是数据对象pt1的方法,而不是类Point创建的clone方法.

#4


Point[] pt2=(Point[])pt1.clone();,clone()调用的是数据对象pt1的方法,而不是类Point创建的clone方法.

#5


为什么不被执行啊?应该怎么改呢?

#6


数组[] 你只能自己控制复制,也就是调用里面每个对象的clone方法!

#7


规则
1,Object 的clone()方法是protected,所以不能从外部直接调用。
   要么override,要么在override的方法内部调用。
2, 调用Object类的clone方法时,如果子类没有实现cloneable接口
   那么会抛出CloneNotSupportedException异常。
3,Object的clone方法是浅拷贝,也就是说对于参照类型的域只拷贝
   指针。如果要实现深拷贝,那么需要覆盖clone类,手动拷贝参照类型。

class TestClone implements Cloneable
{
    private int data;

    public void setData( int i )
    {
        data = i;
    }

    public int getData()
    {
        return data;
    }

     protected Object clone() throws CloneNotSupportedException
    {
        TestCloneTarget newData = new TestCloneTarget();
        newData.data = this.data;
        return newData;
    }
}
我以前做过一个试验给你改一下

#8


    public static void main(String[] args) {
        // TODO 自動生成されたメソッド・スタブ
        Sample sample = new Sample();
        //sample.testClone();
        
        Point[] pt1=new Point[]{new Point(1,1),new Point(3,3),new Point(2,2)};
        Point[] pt2=(Point[])pt1.clone();
        System.out.println(pt1==pt2);   
        pt2[1].x=5;
        pt2[1].y=5;
        System.out.println(pt1[1].x+","+pt1[1].y);    
        System.out.println(pt1[1].hashCode());
        System.out.println(pt2[1].hashCode());
        
        System.out.println();
        
        pt1[1].x=3;
        pt1[1].y=3;
        Point[] pt3= new Point[pt1.length];
        System.arraycopy(pt1,0,pt3,0,pt1.length);
        System.out.println(pt1==pt3);    
        pt3[1].x=5;
        pt3[1].y=5;
        System.out.println(pt1[1].x+","+pt1[1].y);   
        System.out.println(pt1[1].hashCode());
        System.out.println(pt3[1].hashCode());
        
        System.out.println();
        
        try {
            pt1[1].x=3;
            pt1[1].y=3;
            Point[] pt4= new Point[pt1.length];
            for (int i=0; i<pt4.length; i++) {
                pt4[i] = (Point)pt1[i].clone();
            }
            System.out.println(pt1==pt4);    
            pt4[1].x=5;
            pt4[1].y=5;
            System.out.println(pt1[1].x+","+pt1[1].y);   
            System.out.println(pt1[1].hashCode());
            System.out.println(pt4[1].hashCode());
        } catch (Exception e) {
            
        }        
        System.out.println();
        
        int [] numbers = { 2, 3, 4, 5};
        int [] numbersClone = (int[])numbers.clone();
        numbersClone[2] = 0;
        System.out.println("Clone numbers:"+numbers[2]);
        System.out.println("Clone numbers:"+numbersClone[2]);
        
        numbers[2] = 4;
        int [] numbersCopy = new int[numbers.length];
        System.arraycopy(numbers, 0, numbersCopy, 0, numbersCopy.length);
        numbersCopy[2] = 0;
        System.out.println("Copy numbers:"+numbers[2]);
        System.out.println("Copy numbers:"+numbersCopy[2]);

    }

#9


做实验可以看到,数组的拷贝和复制对于基本类型来说是不同的。
比如
      |-----------|
ar1-> | 10 | 20 30|
      |-----------|
如果做附值、ar2=ar1那么就是

      |-----------|
ar1-> | 10 | 20 30| <-ar2
      |-----------|

如果对ar1做拷贝或复制那么结果就是
(ar2=ar1.clone)

       |-----------|
ar1-> | 10 | 20 30|
      |-----------|

      |-----------|
ar2-> | 10 | 20 30|
      |-----------|

但是如果是指针那么效果就一样了
想象一下 10,20,30 都是地址,那么无论怎么拷贝都是地址。
也就是说它们指向的对象永远都是同一个

#10


晕 格式乱了

#11


楼上的有点复杂了,我自己想了一下,这么解决不知对不对

class ArrayTest
{
public static void main(String[] args)
{
Point[] pt1=new Point[]{new Point(1,1),new Point(3,3),new Point(2,2)};
Point[] pt2=new Point[pt1.length];

for(int i=0;i<pt2.length;i++)
{
for(int j=0;j<pt1.length;j++)
{
pt2[i]=(Point)pt1[i].clone();
}
}

//对数数组 pt2 的改变不会影响对象数组 pt1
pt2[1].x=5;
pt2[1].y=5;

System.out.println("数组 pt2 的值:");
for(int i=0;i<pt2.length;i++)
{
System.out.println(pt2[i].x+","+pt2[i].y);
}

System.out.println("\n数组 pt1 的值:");
for(int i=0;i<pt1.length;i++)
{
System.out.println(pt1[i].x+","+pt1[i].y);
}
}
}

class Point implements Cloneable
{
int x,y;
Point(int x,int y)
{
this.x=x;
this.y=y;
}

public Object clone()
{
Object o=null;
try
{
o=super.clone();
}
catch(CloneNotSupportedException e)
{
System.out.println(e.toString());
}
return o;
}
}

#12


刚才的代码贴错了,我的解决方法是这样的,不知是否正确


class ArrayTest
{
public static void main(String[] args)
{
Point[] pt1=new Point[]{new Point(1,1),new Point(3,3),new Point(2,2)};
Point[] pt2=new Point[pt1.length];

for(int i=0;i<pt2.length;i++)
{
pt2[i]=(Point)pt1[i].clone();
}

//对数数组 pt2 的改变不会影响对象数组 pt1
pt2[1].x=5;
pt2[1].y=5;

System.out.println("数组 pt2 的值:");
for(int i=0;i<pt2.length;i++)
{
System.out.println(pt2[i].x+","+pt2[i].y);
}

System.out.println("\n数组 pt1 的值:");
for(int i=0;i<pt1.length;i++)
{
System.out.println(pt1[i].x+","+pt1[i].y);
}
}
}

class Point implements Cloneable
{
int x,y;
Point(int x,int y)
{
this.x=x;
this.y=y;
}

public Object clone()
{
Object o=null;
try
{
o=super.clone();
}
catch(CloneNotSupportedException e)
{
System.out.println(e.toString());
}
return o;
}
}

#1


你的那个Point 的clone方法根本不会执行。

#2


Point[] pt2=(Point[])pt1.clone();,clone()调用的是数据对象pt1的方法,而不是类Point创建的clone方法.

#3


Point[] pt2=(Point[])pt1.clone();,clone()调用的是数据对象pt1的方法,而不是类Point创建的clone方法.

#4


Point[] pt2=(Point[])pt1.clone();,clone()调用的是数据对象pt1的方法,而不是类Point创建的clone方法.

#5


为什么不被执行啊?应该怎么改呢?

#6


数组[] 你只能自己控制复制,也就是调用里面每个对象的clone方法!

#7


规则
1,Object 的clone()方法是protected,所以不能从外部直接调用。
   要么override,要么在override的方法内部调用。
2, 调用Object类的clone方法时,如果子类没有实现cloneable接口
   那么会抛出CloneNotSupportedException异常。
3,Object的clone方法是浅拷贝,也就是说对于参照类型的域只拷贝
   指针。如果要实现深拷贝,那么需要覆盖clone类,手动拷贝参照类型。

class TestClone implements Cloneable
{
    private int data;

    public void setData( int i )
    {
        data = i;
    }

    public int getData()
    {
        return data;
    }

     protected Object clone() throws CloneNotSupportedException
    {
        TestCloneTarget newData = new TestCloneTarget();
        newData.data = this.data;
        return newData;
    }
}
我以前做过一个试验给你改一下

#8


    public static void main(String[] args) {
        // TODO 自動生成されたメソッド・スタブ
        Sample sample = new Sample();
        //sample.testClone();
        
        Point[] pt1=new Point[]{new Point(1,1),new Point(3,3),new Point(2,2)};
        Point[] pt2=(Point[])pt1.clone();
        System.out.println(pt1==pt2);   
        pt2[1].x=5;
        pt2[1].y=5;
        System.out.println(pt1[1].x+","+pt1[1].y);    
        System.out.println(pt1[1].hashCode());
        System.out.println(pt2[1].hashCode());
        
        System.out.println();
        
        pt1[1].x=3;
        pt1[1].y=3;
        Point[] pt3= new Point[pt1.length];
        System.arraycopy(pt1,0,pt3,0,pt1.length);
        System.out.println(pt1==pt3);    
        pt3[1].x=5;
        pt3[1].y=5;
        System.out.println(pt1[1].x+","+pt1[1].y);   
        System.out.println(pt1[1].hashCode());
        System.out.println(pt3[1].hashCode());
        
        System.out.println();
        
        try {
            pt1[1].x=3;
            pt1[1].y=3;
            Point[] pt4= new Point[pt1.length];
            for (int i=0; i<pt4.length; i++) {
                pt4[i] = (Point)pt1[i].clone();
            }
            System.out.println(pt1==pt4);    
            pt4[1].x=5;
            pt4[1].y=5;
            System.out.println(pt1[1].x+","+pt1[1].y);   
            System.out.println(pt1[1].hashCode());
            System.out.println(pt4[1].hashCode());
        } catch (Exception e) {
            
        }        
        System.out.println();
        
        int [] numbers = { 2, 3, 4, 5};
        int [] numbersClone = (int[])numbers.clone();
        numbersClone[2] = 0;
        System.out.println("Clone numbers:"+numbers[2]);
        System.out.println("Clone numbers:"+numbersClone[2]);
        
        numbers[2] = 4;
        int [] numbersCopy = new int[numbers.length];
        System.arraycopy(numbers, 0, numbersCopy, 0, numbersCopy.length);
        numbersCopy[2] = 0;
        System.out.println("Copy numbers:"+numbers[2]);
        System.out.println("Copy numbers:"+numbersCopy[2]);

    }

#9


做实验可以看到,数组的拷贝和复制对于基本类型来说是不同的。
比如
      |-----------|
ar1-> | 10 | 20 30|
      |-----------|
如果做附值、ar2=ar1那么就是

      |-----------|
ar1-> | 10 | 20 30| <-ar2
      |-----------|

如果对ar1做拷贝或复制那么结果就是
(ar2=ar1.clone)

       |-----------|
ar1-> | 10 | 20 30|
      |-----------|

      |-----------|
ar2-> | 10 | 20 30|
      |-----------|

但是如果是指针那么效果就一样了
想象一下 10,20,30 都是地址,那么无论怎么拷贝都是地址。
也就是说它们指向的对象永远都是同一个

#10


晕 格式乱了

#11


楼上的有点复杂了,我自己想了一下,这么解决不知对不对

class ArrayTest
{
public static void main(String[] args)
{
Point[] pt1=new Point[]{new Point(1,1),new Point(3,3),new Point(2,2)};
Point[] pt2=new Point[pt1.length];

for(int i=0;i<pt2.length;i++)
{
for(int j=0;j<pt1.length;j++)
{
pt2[i]=(Point)pt1[i].clone();
}
}

//对数数组 pt2 的改变不会影响对象数组 pt1
pt2[1].x=5;
pt2[1].y=5;

System.out.println("数组 pt2 的值:");
for(int i=0;i<pt2.length;i++)
{
System.out.println(pt2[i].x+","+pt2[i].y);
}

System.out.println("\n数组 pt1 的值:");
for(int i=0;i<pt1.length;i++)
{
System.out.println(pt1[i].x+","+pt1[i].y);
}
}
}

class Point implements Cloneable
{
int x,y;
Point(int x,int y)
{
this.x=x;
this.y=y;
}

public Object clone()
{
Object o=null;
try
{
o=super.clone();
}
catch(CloneNotSupportedException e)
{
System.out.println(e.toString());
}
return o;
}
}

#12


刚才的代码贴错了,我的解决方法是这样的,不知是否正确


class ArrayTest
{
public static void main(String[] args)
{
Point[] pt1=new Point[]{new Point(1,1),new Point(3,3),new Point(2,2)};
Point[] pt2=new Point[pt1.length];

for(int i=0;i<pt2.length;i++)
{
pt2[i]=(Point)pt1[i].clone();
}

//对数数组 pt2 的改变不会影响对象数组 pt1
pt2[1].x=5;
pt2[1].y=5;

System.out.println("数组 pt2 的值:");
for(int i=0;i<pt2.length;i++)
{
System.out.println(pt2[i].x+","+pt2[i].y);
}

System.out.println("\n数组 pt1 的值:");
for(int i=0;i<pt1.length;i++)
{
System.out.println(pt1[i].x+","+pt1[i].y);
}
}
}

class Point implements Cloneable
{
int x,y;
Point(int x,int y)
{
this.x=x;
this.y=y;
}

public Object clone()
{
Object o=null;
try
{
o=super.clone();
}
catch(CloneNotSupportedException e)
{
System.out.println(e.toString());
}
return o;
}
}