Я провел некоторый тест в Java, и кажется, что по умолчанию индекс и граница каждый раз пересчитываются.
В соответствии со спецификацией языка Java это:
for(int i = 0 ; i < foo.getLength() ; i++){ }
означает, что getLength()
вызывается на каждой итерации цикла.Java-компиляторам только разрешено перемещать вызов getLength()
из цикла, если они могут эффективно доказать , что он не изменяет наблюдаемое поведение.(Например, если getLength()
просто возвращал одно и то же значение из одной и той же переменной каждый раз, то есть большой шанс, что JIT-компилятор может встроить вызов и , тогда сделает вывод, что он может выполнить оптимизацию подъемаНо если getLength()
предполагает получение длины параллельной или синхронизированной коллекции, есть вероятность, что оптимизация будет разрешена ... из-за возможных действий со стороны других потоков.)
Так что это то, что компилятор разрешено делать.
Интересно, возможно ли активировать такую функцию в JVM HotSpot?
Простой ответ* Нет. 1028 *
Вы, кажется, предлагаете переключатель компилятора, который сообщает / позволяет компилятору игнорировать правила JLS.Там нет такого переключателя.Такой переключатель будет ПЛОХАЯ ИДЕЯ .Это может привести к поломке правильных / действующих / работающих программ.Учтите это:
class Test {
int count;
int test(String[] arg) {
for (int i = 0; i < getLength(arg); i++) {
// ...
}
return count;
}
int getLength(String[] arg) {
count++;
return arg.length;
}
}
Если бы компилятору было разрешено перемещать вызов getLength(arg)
из цикла, это изменило бы количество раз, которое вызывался метод, и, следовательно, изменило значение, возвращаемоеtest
метод.
Оптимизация Java, которая изменяет поведение правильно написанной программы Java, не является допустимой оптимизацией.(Обратите внимание, что многопоточность приводит к мутности воды. JLS и, в частности, правила модели памяти, позволяют компилятору выполнять оптимизации, которые могут привести к тому, что разные потоки увидят несовместимые версии состояния приложения ... если они не синхронизируютсяправильно, что приводит к неправильному поведению с точки зрения разработчика. Но настоящая проблема с приложением, а не с компилятором.)
Кстати, более убедительно причина того, что вы не должны изменять переменную цикла в теле цикла, заключается в том, что это затрудняет понимание вашего кода.