#java #строки #heap
Один из вопросов в 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. Объясните, пожалуйста, в чем я ошибся?
Ответы
Ответ 1
Оператор += можно расписать так s = s + " " + i; Поэтому на каждой итерации будет создаваться по одной строке и присваиваться переменной s. Т.е. Java сразу сложит все в одну строку вместо того, чтобы создавать её по частям. Если бы мы вынесли " " + i в отдельную переменную, а потом добавили к s, тогда бы был вариант, о котором Вы подумали.Ответ 2
Давайте посмотрим чем будет заниматься 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 похож на правду.
Комментариев нет:
Отправить комментарий