Какова цель использования локальной переменной для хранения глобальной переменной?

Я взглянул на исходный код String.hashcode () . Это была реализация в 6-b14, которая уже была изменена.

public int hashCode() {
        int h = hash;
        if (h == 0) {
            int off = offset;
            char val[] = value;
            int len = count;

            for (int i = 0; i < len; i++) {
                h = 31*h + val[off++];
            }
            hash = h;
        }
        return h;
}

Мой вопрос об этой строке:

int len = count;

Где count - глобальная переменная, представляющая количество символов в строке.

Почему локальная переменная len используется здесь для условия цикла, а не для самой глобальной переменной? Потому что нет никаких манипуляций с переменной, только чтение. Является ли хорошей практикой использование локальной переменной, если для чтения или записи в нее используется глобальное поле? Если ответ «да», зачем читать?

7 голосов | спросил Steve Benett 13 J0000006Europe/Moscow 2014, 18:02:53

3 ответа


0

Обыскивая класс String, я нашел комментарий об этом странном назначении локальной переменной в String.trim () чтение метода "avoid getfield opcode".

public String trim() {
    int len = value.length;
    int st = 0;
    char[] val = value;    /* avoid getfield opcode */

    while ((st < len) && (val[st] <= ' ')) {
        st++;
    }
    while ((st < len) && (val[len - 1] <= ' ')) {
        len--;
    }
    return ((st > 0) || (len < value.length)) ? substring(st, len) : this;
}

Так что, похоже, все дело в производительности, как указал Фрэнк Олшевски .

В байт-коде Java переменная экземпляра фактически ссылается на объект и имя (используя инструкцию GETFIELD). Без оптимизации виртуальная машина должна выполнить больше работы для доступа к переменной.

Таким образом, потенциальное снижение производительности кода заключается в том, что он использует относительно дорогую инструкцию GETFIELD при каждом прохождении цикла. Локальное присвоение в методе устраняет необходимость в GETFIELD каждый раз в цикле.

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

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

ответил MicSim 13 J0000006Europe/Moscow 2014, 20:34:49
0

Доступ к локальной переменной быстрее, чем к переменной экземпляра. Также новый код Java 8 (см. Ответ Anubians) учитывает это. По этой причине они используют локальную переменную h для вычисления хеша и не обращаются к переменной экземпляра this.hash и создайте локальный указатель char val[] = value;. Но с учетом этого я не знаю, почему они не используют i < val.length; или даже лучше z = val.length; i < z; в цикле for, но i < value.length;.

ответил Frank Olschewski 13 J0000006Europe/Moscow 2014, 18:30:42
0

Если count можно изменить, то вам нужна локальная переменная. Если у вас идет многопоточность, вам нужна локальная переменная. Безопаснее всего создать локальную переменную. Тем не менее, это не обязательно обязательно.

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

Это практически бесполезно, поэтому в Java 8 это выглядит так:

public int hashCode() {
    int h = hash;
    if (h == 0 && value.length > 0) {
        char val[] = value;

        for (int i = 0; i < value.length; i++) {
            h = 31 * h + val[i];
        }
        hash = h;
    }
    return h;
}

У них даже больше нет счета, они используют value.length, где value - окончательный массив символов.

Они делают char val[] = value, но это всего лишь справка, и она абсолютно не нужна.

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

ответил Anubian Noob 13 J0000006Europe/Moscow 2014, 18:06:20

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

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132