Ошибка в моделировании экзамена OCJP: сколько объектов действительно создано?
В симуляции для сертификации OCJP я нашел этот вопрос:
1. StringBuffer s1 = new StringBuffer("abc");
2. StringBuffer s2 = s1;
3. StringBuffer s3 = new StringBuffer("abc");
How many objects are created ?
Они утверждают, что правильный ответ равен 4, поскольку они указывают:
s1 is one object, s2 is another object,
s3 is another object and "abc" is another String Object .
Но для меня это неправильно, и оно должно быть 3, потому что s1
и s2
- это один и тот же объект. Как вы думаете?
Ответы
Ответ 1
Вы правы, что ответ не 4 объекта.
Однако вопрос "сколько объектов создается" неоднозначен. Проблема в том, что один из трех объектов не создается при выполнении кода. В частности, объект String
, соответствующий литералу "abc"
, фактически создается при загрузке кода. Когда этот код выполняется, создаются два объекта StringBuffer
, и используется существующий объект String
.
И на самом деле это сложнее, поскольку в момент загрузки класса возможно создание другого временного объекта String
и затем отбрасывается после его интернирования;
-
Если литерал "abc"
уже загружен в другой класс, то он будет использоваться.
-
Не указано, если реализация пула строк создает новую копию String
, если она должна быть помещена в пул.
Если вопрос более точно не сформулирован, то нет единого правильного ответа. Лучшее, что вы можете сказать:
- При запуске кода создаются два объекта
StringBuffer
.
- Один или два объекта
String
создаются при загрузке кода.
Тогда возникает вопрос, следует ли считать частные char[]
объекты, которые являются частью объектов StringBuffer
и String
. Это может увеличить количество объектов до 8.
Ответ 2
Да определенно 3 Object.both s1 и s2, ссылающиеся на одно и то же место. поэтому s1, s2 и "abc" являются объектами здесь. Может быть, лучше не следовать этой ссылке.
Ответ 3
КОРРЕКЦИЯ
Должно быть 3 объекта:
1. StringBuffer s1 = new StringBuffer("abc");
В памяти s1 и "abc" будут созданы два объекта. Это связано с тем, что строки интернированы, а литералы добавляются в пул памяти.
2. StringBuffer s2 = s1;
Здесь не будет создан объект, потому что s2 укажет на "abc", созданный как часть s1
3. StringBuffer s3 = new StringBuffer("abc");
Для s3 будет создан только один объект.
Ответ 4
Как насчет:
1. StringBuffer s1 = new StringBuffer("abc");
1 builder
object + 1 char[]
object + (1 Строковый литерал, если он создан)
2. StringBuffer s2 = s1;
Нет новых объектов.
3. StringBuffer s3 = new StringBuffer("abc");
1 builder
объект + 1 char[]
объект
A StringBuilder
инкапсулирует поддержку char [] внутри, которая является объектом.
Как @StephenC говорит, что вопрос неоднозначен.
Ответ 5
3 или 4, в зависимости от реализации. Некоторые компиляторы создавали бы только один объект String для константы "abc" и ссылались бы на него столько раз, сколько необходимо, а другие компиляторы могли бы создать один объект на константу. AFAIK, это не было санкционировано всеми версиями спецификаций языков, и в будущем это может измениться.
Или больше, в зависимости от реализации StringBuffer (который мог бы активно создавать char [] и копировать строку инициализации, в отличие от ленивой реализации, которая откладывает это до тех пор, пока содержимое StringBuffer не будет действительно изменено). Опять же, это не должно регулироваться языком. И, BTW, массивы считаются Object
для целей вопроса? А что, если реализация StringBuffer хранит информацию в структуре JNI? Что это значит как объекты? Я просто пытаюсь пересмотреть свою точку зрения о деталях реализации, не связанных с языком.
Тест не должен задавать такие вопросы, если только речь идет о конкретной реализации и/или версии JLS.
Совершенно ясно, что аргумент , который они дают для ответа 4, совершенно неверен. Назначение s2
не создает никакого нового объекта.