使用System.arraycopy()容易忽略的问题

arraycopy()方法在JDK中是这样介绍的:

void arraycopy(Object src,int srcPos,Object dest,int destPos,int length)
Copies an array from the specified source array, beginning at the specified position, to the specified position of the destination array.
A subsequence of array components are copied from the source array referenced by src to the destination array referenced by dest.
The number of components copied is equal to the length argument. The components at positions srcPos through srcPos+length-1 in
the source array are copied into positions destPos through destPos+length-1, respectively, of the destination array.
If the src and dest arguments refer to the same array object, then the copying is performed as if the components
at positions srcPos through srcPos+length-1 were first copied to a temporary array with length components
and then the contents of the temporary array were copied into positions destPos through destPos+length-1 of the destination array.

下面简单介绍一下:

参数:
src:源数组;	srcPos:源数组要复制的起始位置;
dest:目的数组;	destPos:目的数组放置的起始位置;	length:复制的长度。

简单描述就是从src的srcPos位置拷贝length长度的数据到dest的destPos位置,如果src和dest是同一个对象的话,则相当于先将数据拷贝到一个临时的数组,然后再覆盖数组中destPos开始的一段数据。

常见的使用方法:

int[] is = new int[]{1,2,3,4,5}; 
int[] is2 = new int[is.length];
System.arraycopy(is, 0, is2, 0, is.length);
System.out.println(Arrays.toString(is2));

 

但是,使用此方法有个很严重的问题,由于它的复制是浅复制(shallow copy),复制后的数组与原数组中的数据指向同一个位置.

示例如下:

public class Clone2 {
    public static void main(String[] args) {
        Te[] t1 = new Te[1];
        t1[0] = new Te("a");
        Te[] t2 = new Te[1];
        System.out.println(t1[0]);
        //调用
        System.arraycopy(t1, 0, t2, 0, 1);
        System.out.println(t2[0]);
    }
}
class Te{
    String name;
    Te(String name) {
        this.name = name;
    }
}
//输出
/*
CloneTest.Te@74a14482
CloneTest.Te@74a14482
*/

从上面的输出可以看出复制后的数组中的元素与原来指向了一个位置,这样子很容易引发严重的问题.一旦我们更改了原来的数据,复制后的数据也会随之改变.

例如:

public class Clone2 {
    public static void main(String[] args) {
        Te[] t1 = new Te[1];
        t1[0] = new Te("a");
        Te[] t2 = new Te[1];
        System.out.println("t1修改前:"+t1[0]);
        //修改t1[0]
        t1[0].name = "2";
        System.out.println("t1修改后:"+t1[0]);
        //调用
        System.arraycopy(t1, 0, t2, 0, 1);
        System.out.println("t2:"+t2[0]);
    }
}
class Te{
    String name;
    Te(String name) {
        this.name = name;
    }
    @Override
    public String toString() {
        return "Te{" +
                "name='" + name + '\'' +
                '}';
    }
}
//输出:
/*
t1修改前:Te{name='a'}
t1修改后:Te{name='2'}
t2:Te{name='2'}
 */
对t1[0]进行修改,但是由于t1[0]和t2[0]引用了同一个对象,因此后者也会随之改变,在平时的使用中如果不注意的话会引起相当大的问题。
 
而且由于System.arraycoppy()是JDK中的native方法,JDK中有关于集合,数组操作的基本上都调用此方法,因此在使用这些的时候要注意。
 
 
 
posted @ 2016-08-25 19:59  山里的小房子  阅读(6585)  评论(1编辑  收藏  举报