System.arraycopy не генерирует исключение ArrayIndexOutOfBoundsException

Я не совсем понимаю, как работает System.arraycopy. Имейте простой пример:

String[] arr = {"a"};
String[] copyArr = new String[10];
System.arraycopy(arr, 0, copyArr, 0, 1);
System.out.println(Arrays.toString(copy));

Я понимаю это как «скопировать 1 элемент из arr, начиная с [0], чтобы скопироватьArr в позицию [0]». И это нормально. Теперь я меняю его на:

String[] arr = {"a"};
String[] copyArr = new String[10];
System.arraycopy(arr, 1, copyArr, 0, 0);
System.out.println(Arrays.toString(copy));

Поскольку arr.length равен 1, а единственный индекс, который мы можем вызвать, равен [0], я ожидал, что он выдаст исключение ArrayIndexOutOfBoundsException, но это не так.

Итак, вопрос в том, в чем разница между этими двумя строками ниже и почему первая возможна, если нет элемента в [1] в src (поскольку его длина равна 1), это собственный метод, так как он реализован внутри?

System.arraycopy(src, 1, dest, 0, 0);
System.arraycopy(src, 0, dest, 0, 0);

Что интересно, когда мы изменим его на:

System.arraycopy(src, 2, dest, 0, 0);

есть ArrayIndexOutOfBoundsException (и этот случай описан в документах, потому что srcPos+length > src.length).


person swch    schedule 03.11.2016    source источник
comment
Потому что так написано в документации? Или вы хотите знать, почему так написано?   -  person Tunaki    schedule 03.11.2016


Ответы (2)


В src[1] есть массив нулевой длины, который вы можете "скопировать". В src[2] нет массива нулевой длины, поэтому возникает исключение.

Представьте себе массив размером 3 и содержащиеся в нем подмассивы (показаны размеры подмассивов):

[ 0 ][ 1 ][ 2 ]
[ -----3------]
     [----2---]
          [-1-]
             []

То же самое для начала массива и каждой позиции между индексами.

person Kayaman    schedule 03.11.2016
comment
было бы здорово, если бы вы могли немного уточнить свой ответ - person sanbhat; 03.11.2016
comment
Спасибо, я бы просто добавил, что в реализации arraycopy есть фрагмент кода, который выглядит так if (length==0) { return; } и его можно найти в вопрос связан @FaigB и показывает, как он реализован внутри - person swch; 03.11.2016

Вот вам тема

из кода понятно:

// Check if the ranges are valid
if  ( (((unsigned int) length + (unsigned int) src_pos) > (unsigned int) s->length())
   || (((unsigned int) length + (unsigned int) dst_pos) > (unsigned int) d->length()) )   {
  THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException());
}
person FaigB    schedule 03.11.2016