Один из вопросов в OCA7 выглядит так:
public class Mounds {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
String s = new String();
for (int i = 0; i < 1000; i++) {
s += " " + i;
sb.append(s);
}
// done with loop
} }
Если сборщик мусора не будет работать во время исполнения кода, сколько примерно объектов будет существовать в памяти, когда цикл завершится?
A. Меньше 10;
B. Примерно 1000;
C. Примерно 2000;
D. Примерно 3000;
E. Примерно 4000.
Со StringBuilder все понятно: он mutable, как создался, так один и остался. А поскольку String является immutable классом, каждый раз создается новый объект. Сперва я подумал, что правильный ответ - B, 1000 объектов по количеству итераций. Но потом присмотрелся к телу цикла:
s += " " + i;
Здесь мы видим, что каждый раз к пробелу (который создается в пуле строк лишь единожды) каждый раз конкатенируется значения i, которое, соответственно, каждый раз создает новую строку со значением i, то есть "0", "1", "2" и так далее, которые затем превращаются в новые строки "0", "0 1", "0 1 2" и так далее. И подумал, что правильный ответ - C, 2000 объектов - по одному на каждую новую строку s и каждую новую строку значения i.
Однако в книжке приводится, что правильный ответ - B. Объясните, пожалуйста, в чем я ошибся?
Оператор += можно расписать так s = s + " " + i; Поэтому на каждой итерации будет создаваться по одной строке и присваиваться переменной s. Т.е. Java сразу сложит все в одну строку вместо того, чтобы создавать её по частям. Если бы мы вынесли " " + i в отдельную переменную, а потом добавили к s, тогда бы был вариант, о котором Вы подумали.
Давайте посмотрим чем будет заниматься JVM при выполнении этого задания. Декомпиляция примера дает такой результат:
public class Mounds {
public Mounds() { // тут конструктор по умолчанию
}
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
String s = new String();
for(Object i = 0; i < 1000; ++i) {
sb.append((String)i); // а тут сюрприз!
}
}
}
Хотя классическое описание операции объединения строк с помощью оператора +
предполагает следующую конструкцию:
s = new StringBuilder(s).append(" ").append((String)i)).toString()
в которой будет создано аж три объекта:
new StringBuilder()
(String)i
new String()
в результате работы последнего toString()
, мы видим что компилятор не стал размениваться на подобные мелочи и использовал имеющийся StringBuilder
чтобы сократить количество объектов и операций к мнимому. Т.о. каждый цикл создается только новый объект String
в момент преобразования числа к строке, и ответ 1000 похож на правду.
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Виртуальный выделенный сервер (VDS) становится отличным выбором
Я никак не понимаю, что я буду делать на работе, выучив джавуНазовите, пожалуйста, примеры программ, к-е на ней чаще пишутся
Столкнулся с проблемой при запуске проекта Spring MVCПосле запуска бесконечное развертывание происходит
Есть четыре классаПервый класс товары
В HashMap хрянятся ключ-значение, пользователь вводит ключ, программа выводит значениеКак это реализовать?