Метод System.arraycopy() - Вопросы
Всего: 5 вопросов
1. Что делает метод System.arraycopy() и какие у него параметры?
Что делает метод 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() и когда?
Какие исключения выбрасывает 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() и 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?
Почему System.arraycopy() быстрее ручного цикла for?
Метод объявлен как native — его тело реализовано на уровне JVM, а не на Java. JVM выполняет копирование напрямую в памяти (аналогично низкоуровневым операциям вроде memmove), минуя накладные расходы обычного байткода: проверку границ на каждой итерации, инкремент счётчика, вызовы. Поэтому на нём построены Arrays.copyOf(), Arrays.copyOfRange() и внутренности многих коллекций. На небольших массивах разница с циклом незаметна, но на десятках тысяч элементов и больше System.arraycopy() заметно быстрее и надёжнее.