Looking for java Keywords? Try Ask4Keywords

Java Language Pitfall - чрезмерное использование примитивных типов обертки неэффективно


пример

Рассмотрим эти два фрагмента кода:

int a = 1000;
int b = a + 1;

а также

Integer a = 1000;
Integer b = a + 1;

Вопрос: Какая версия более эффективна?

Ответ: Две версии выглядят почти одинаково, но первая версия намного эффективнее второй.

Вторая версия использует представление для чисел, которые используют больше пространства, и опирается на автоматическое боксирование и автоматическое распаковывание за кулисами. Фактически вторая версия прямо эквивалентна следующему коду:

Integer a = Integer.valueOf(1000);               // box 1000
Integer b = Integer.valueOf(a.intValue() + 1);   // unbox 1000, add 1, box 1001

Сравнивая это с другой версией, использующей int , есть четыре дополнительных вызова метода, когда используется Integer . В случае valueOf каждый вызов будет создавать и инициализировать новый объект Integer . Вся эта дополнительная работа по боксу и распаковке, вероятно, сделает вторую версию на порядок медленнее, чем первая.

В дополнение к этому, вторая версия выделяет объекты в куче в каждом вызове valueOf . Хотя использование пространства зависит от платформы, оно, вероятно, будет находиться в области 16 байт для каждого объекта Integer . Напротив, версия int нуждается в нулевом избытке кучи, предполагая, что a и b являются локальными переменными.


Еще одна важная причина, по которой примитивы быстрее, чем их эквивалент в коробке, - это то, как их соответствующие типы массивов выкладываются в памяти.

Если вы берете int[] и Integer[] в качестве примера, то в случае int[] значения int смежно располагаются в памяти. Но в случае Integer[] это не значения, которые выложены, а ссылки (указатели) на объекты Integer , которые, в свою очередь, содержат фактические значения int .

Помимо того, что это дополнительный уровень косвенности, это может быть большой танк, когда дело доходит до местоположения кеша при повторении значений. В случае int[] процессор может извлекать все значения в массиве в его кеш-память сразу, потому что они смежны в памяти. Но в случае Integer[] процессор потенциально должен выполнить дополнительную выборку памяти для каждого элемента, так как массив содержит только ссылки на фактические значения.


Короче говоря, использование примитивных типов обертки относительно дорого как в ресурсах ЦП, так и в памяти. Использование их излишне эффективно.