Влияние производительности автоупаковки

Обычно компилятор генерирует код для выполнения упаковки и распаковывания. Но что делает компилятор, если помещенные в коробку значения не нужны? (Стандарт Oracle) компилятор, достаточно умный для оптимизации его далеко?

Смотрите на этот метод:

public static void requireInRange(int index, Object[] array) {
    if(index < 0 || index >= array.length)
        throw new IndexOutOfBoundsException();
}

Единственная релевантная информация array.length, таким образом, было бы бесполезно упаковать каждое значение массива, например. Как в этом коде:

int[] anArray = {3, 4, 2};
requireInRange(3, anArray);

Компилятор на самом деле введет код для упаковки каждого значения массива?

13
задан deamon 7 August 2010 в 13:53
поделиться

3 ответа

В вашем коде нет автобокса. Фактически, учитывая:

public static void requireInRange(int index, Object[] array) {
   ...
}

int[] anArray = {3, 4, 2};
requireInRange(3, anArray); // DOES NOT COMPILE!!!

В то время как int может быть автоматически упакован в Целое число , int [] не будет автоматически упакован НЕ to Integer [] от Java. Для этого вы можете написать библиотечные функции, но язык не облегчит это преобразование.

Это на самом деле источник многих недоразумений, например, относительно Arrays.asList (anIntArray) «сломан», потому что вместо возврата List , то, что возвращается, фактически является одноэлементным List .


А как насчет производительности ???

Цитата из Java Language Guide / Autoboxing :

Неуместно использовать автобоксирование и распаковку для научных вычислений или других числовых вычислений, зависящих от производительности. код. Целое число не заменяет int ; автобоксирование и распаковка стирают различие между примитивными типами и ссылочными типами, но не устраняют его.

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

    System.out.println(
        ((Integer) 0) == ((Integer) 0)
    );
    // true

    System.out.println(
        ((Integer) 10000) == ((Integer) 10000)
    );
    // false (implementation-specific)

Здесь произошло следующее: когда 0 автоматически помещается в штучную упаковку, фактически не создается экземпляр new Integer : значения в определенном диапазоне кэшируются для целей автобокса, чтобы повысить производительность. 10000 в большинстве реализаций, вероятно, выпадает из этого диапазона, но некоторые реализации JVM позволяют при необходимости указывать диапазон кеширования.


Но я просто хочу получить длину массива !!!

Есть много способов упростить requireInRange работу с любыми типами массивов. К сожалению, работа с массивом примитивов Java часто требует большого количества повторений. Это означает предоставление перегрузок для int [] , логического [] , байта [] , объекта [] и т. Д. Отдельно.

Более лаконичный вариант - использовать отражение, но в этом есть свои плюсы и минусы. Вообще говоря, отражение не должно быть предпочтительным решением для большинства сценариев.

Сказав это, java.lang.reflect.Array действительно имеет метод int getLength (Object array) static , который может возвращать длину ЛЮБОГО массив. Это не типобезопасно (как и большинство механизмов отражения); передача не-массива компилируется, но вызывает исключение IllegalArgumentException во время выполнения.

Связанные вопросы

41
ответ дан 1 December 2019 в 17:47
поделиться

Будет ли компилятор вставлять код на самом деле для упаковки каждого значения массива?

Компилятор отклонит код, потому что int [] не может быть передано в метод, который принимает параметр Object [] .

Автобоксирование выполняется только для отдельных примитивных значений, а не для целых массивов.

4
ответ дан 1 December 2019 в 17:47
поделиться

Если есть сомнения, вы можете предположить, что компилятор не оптимизирует код. Обычно это дословный перевод кода.

Кроме того, если вы сомневаетесь, вы можете предположить, что JVM очень хорошо справляется с оптимизацией кода во время выполнения. Я бы не стал думать, что это имеет значение, если у вас нет веских оснований (например, профилировщика) подозревать, что это проблема.

2
ответ дан 1 December 2019 в 17:47
поделиться
Другие вопросы по тегам:

Похожие вопросы: