Метод System.arraycopy() - Вопросы

Всего: 5 вопросов

1. 

Что делает метод System.arraycopy() и какие у него параметры?

System.arraycopy() копирует заданное количество элементов из одного массива в другой (или в тот же самый). Это статический метод класса java.lang.System с сигнатурой arraycopy(Object src, int srcPos, Object dest, int destPos, int length): src — массив-источник, srcPos — индекс начала копирования в источнике, dest — массив-приёмник, destPos — индекс, с которого пишем в приёмник, length — число копируемых элементов. Метод ничего не возвращает (void) и не создаёт новый массив — приёмник должен существовать и быть достаточно длинным заранее.

2. 

Какие исключения выбрасывает System.arraycopy() и когда?

NullPointerException — если src или dest равны null. ArrayIndexOutOfBoundsException — если srcPos, destPos или length отрицательны, либо диапазон srcPos + length или destPos + length выходит за пределы соответствующего массива. ArrayStoreException — если элемент из src нельзя записать в dest из-за несовместимости типов. Важно: если часть элементов уже была скопирована до момента ошибки, эти изменения в dest останутся — метод не откатывает уже выполненную часть.

3. 

Чем System.arraycopy() отличается от Arrays.copyOf() и clone()?

System.arraycopy() не создаёт новый массив: он копирует часть (или весь) массив в уже существующий приёмник, в том числе с перекрытием диапазонов. Arrays.copyOf(array, newLength) создаёт новый массив нужной длины и копирует элементы, а внутри использует System.arraycopy(). array.clone() тоже создаёт новый массив — полную поверхностную копию той же длины и типа. Вывод: если приёмник уже есть и нужна лишь часть данных — берите System.arraycopy(); если нужен именно новый массив — короче Arrays.copyOf() или clone().

4. 

Можно ли копировать массив сам в себя, если исходный и целевой диапазоны перекрываются?

Да, и это безопасно даже при перекрывающихся диапазонах. System.arraycopy() ведёт себя так, будто элементы сначала копируются во временную область, поэтому они не перезатирают друг друга раньше времени. Например, для {1, 2, 3, 4, 5, 6, 7, 8} вызов System.arraycopy(array, 1, array, 3, 3) даёт [1, 2, 3, 2, 3, 4, 7, 8]. Наивный цикл for, копирующий элементы по одному в порядке возрастания индекса, на таком перекрытии дал бы неверный результат — затёр бы значения ещё до того, как их успели прочитать.

5. 

Почему System.arraycopy() быстрее ручного цикла for?

Метод объявлен как native — его тело реализовано на уровне JVM, а не на Java. JVM выполняет копирование напрямую в памяти (аналогично низкоуровневым операциям вроде memmove), минуя накладные расходы обычного байткода: проверку границ на каждой итерации, инкремент счётчика, вызовы. Поэтому на нём построены Arrays.copyOf(), Arrays.copyOfRange() и внутренности многих коллекций. На небольших массивах разница с циклом незаметна, но на десятках тысяч элементов и больше System.arraycopy() заметно быстрее и надёжнее.

Страница 1 из 1