System.arraycopy方法的简短总结

c/c++

浏览数:75

2019-3-28

API使用场景

在JDK研发团队的开发过程中,对集合的操作过程中常会使用到此方法。

API参数

public static native void arraycopy(
       Object src,  //源数组
       int srcPos,  //源数组的读取起始位置
       Object dest, //目标数组
       int destPos, //目标数据中的写入起始位置
       int length   //要复制的数组元素的数量
       );

Functions

  1. 将指定源数组的数组从指定位置复制到目标数组的指定位置。数组组件的子序列由src引用的源数组复制到dest引用的目标数组。复制的组件数等于length。源序列中从srcPos到srcPos+length-1的序列复制到目标序列的destPos到destPos+length-1位置。
  2. 如果src和dest参数引用的是相同的数组对象,则首先把源数组srcPos到srcPos+length-1的组件复制到具有与此相同长度的临时数组里,然后再把临时数组的内容复制到目标数组destPos到destPos+length-1位置。
  3. 如果dest为null,则抛出NullPointerException;如果src为空,则抛出NullPointerException,并且不修改目标数组。
  4. 抛出ArrayStoreException的情况(前7种情况不会修改dest):
    1)src参数指向的不是数组对象
    2)dest参数指向的不是数组对象
    3)src参数和dest参数指向的对象类型不是同一种基本类型的数组
    4)src参数指向由原始组件类型组成的数组,dest参数指向由引用组件类型组成的数组
    5)dest参数指向由原始组件类型组成的数组,src参数指向由引用组件类型组成的数组
    6)srcPos+length>src.length
    7)destPos+length>dest.length
    8)对于任意i满足:srcPos <= i <= (srcPos+length-1),src.get(i)无法转换为dest的成员类型。(这种情况下,令k为小于length的非负整数,假设此时使src[srcPos+k]不能转换为目标数组的成员类型,当抛异常时srcPos到srcPos+k-1的源数组成员已经通过destPos+k-1被复制到目标数组的destPos位置,目标数组的剩余位置不会被修改。这种情况仅适用于两个数组都具有引用类型的成员类型的情况)

方法特性

1、总的来说,复制方式属于浅复制

  • 复制的过程只是引用变量的二次传递。
  • 一维数组的复制:属性值传递,修改则不会影响副本
  • 二维数组的复制:复制的是第一维的引用列表,副本和原数组的指向是相同的堆地址,这个时候,值变动的影响是双向的

2、此方法不是线程安全的,必要时要加锁限制。
3、相比for遍历复制,此方法更加高效。

  • 原因很简单,该方法使用内存块整体读取与复制,相比for的遍历寻址来说自然会快,不过这个速度优势在数组成员比较多的时候才会有较明显的体现。下面贴出native方法中关键部分copy的方法c++代码:
void _Copy_conjoint_jints_atomic(jint* from, jint* to, size_t count) {
    if (from > to) {
      jint *end = from + count;
      while (from < end)
        *(to++) = *(from++);
    }
    else if (from < to) {
      jint *end = from;
      from += count - 1;
      to   += count - 1;
      while (from >= end)
        *(to--) = *(from--);
    }
}