8 июня 2023 1262
Этой публикацией мы начинаем серию небольших статей с разбором “сложных” заданий из сертификации для Java-разработчиков, чтобы помочь вам подготовиться к сдаче сертификационного экзамена и помочь вам лучше понять, как работает Java и как эффективнее использовать его в своих проектах.

Итак, один из подвопросов, традиционно выносимых на экзамен – будь это сертификация Oracle или сертификации для Java-разработчиков от Учебного центра IBS – интересуется разработкой кода с использованием классов-оболочек, в частности, Boolean, Double или, скажем, Integer. Такая задача может быть сформулирована в следующей форме:

photo_2023-06-05_10-27-43.jpg

Как мы видим, в вопросе задействованы два класса-оболочки, а именно Boolean (в лице его статического фабричного метода) и Integer. Следует отметить, что для нашего экзамена характерен подход, сочетающий в себе сразу несколько тестируемых аспектов. Поэтому не всегда очевидно, чем именно задача интересуется: тем, как работают "фабрики", механизмом автоупаковки/распаковки или оператором сравнения и т. д.

Обсудим все по-порядку. Практически в каждом классе-оболочке есть два популярных статических метода для создания объекта: valueOf(), который принимает подстилающий примитив, и parseXXX(), который – как и всякий парсер – принимает стринг (здесь вместо XXX надо подставить, например, Double, Int и т.д.). Исключением является класс Character: в нем парсера нет. Встречаются и перегруженные парсеры, где можно указать систему счисления, но наш экзамен таких тонкостей не касается.

Далее, присваивание примитива к ссылке на класс-оболочку приводит к автоупаковке (примитив, разумеется, должен быть при этом соответствующего типа), поэтому такой подход часто используется при создании объектов, одно из преимуществ – возможность вызвать конструктор, хотя этот способ был депрецирован еще в 9-й версии. Постараемся дать ответ, почему такая депрекация вообще понадобилась.

Мы знаем, что при вызове конструктора через ключевое слово new возможны два результата: мы получим совершенно новый объект данного типа, либо вылетит исключение. Из-за такой ограниченности функционала конструкторов предпочтение отдается фабричным методам, которые – в отличие от любого конструктора – способны вернуть ссылку на уже существующий объект.

И вот что интересно: поскольку класс-оболочка Integer является немутирующим, два объекта этого класса с одним и тем же значением способны взаимозаменять друг друга. Вот почему нет никакой необходимости иметь два разных объекта с одинаковым подстилающим значением. Мало того, помимо экономии памяти мы получаем также возможность сравнивать объекты через == вместо вызова метода equals(Object o). В частности, для класса Integer такой подход популярен с объектами, чьи значения лежат в пределах диапазона байта, т.е. от -128 до 127. (И если тут возникает ощущение дежа-вю, то все правильно: со стрингами аналогичная история, мы предпочитаем пользоваться строковыми константами в двойных кавычках вместе вызова, скажем, new String("5").

Фабричные методы обладают и другими преимуществами. Например, мы можем иметь несколько аналогичных методов с разными именами, но одинаковыми списками формальных параметров. А вот с конструкторами такой фокус не пройдет: их можно только перегрузить.

В книге Джошуа Блока, "Effective Java", приведен полный список преимуществ статических фабричных методов над конструкторами. Еще одна выгода в том, что конструктор способен вернуть объект одного типа, а вот фабричный метод может вернуть что угодно, если это не противоречит задекларированному типу возвращаемого значения. Одно из наиболее наглядных и понятных проявленией – это имплементация интерфейсов, где можно аккуратно скрыть специфические детали реализации.

Метод Boolean.valueOf()может вернуть одно из двух значений, причем это константные объекты, а именно, Boolean.TRUE и Boolean.FALSE. Именно эти объекты будут использоваться раз за разом, не требуя дополнительного выделения памяти, что не представляется возможным с ключевым словом new.

Далее, большинство оболочечных классов бросают исключение в случае null-аргумента или стринга, чей формат нарушает требования к подстилающему примитиву (например, если бы мы вызвали Integer.valueOf() с аргументом "five", а не "5"). Но здесь следует отметить, что парсер класса java.lang.Boolean всегда тестирует аргумент: во-первых, существует ли он и, во-вторых, содержит ли значение "true" при любом сочетании букв в верхнем и нижнем регистрах. Если да, булевый парсер вернет Boolean.TRUE, а в противном случае – Boolean.FALSE. Другими словами, парсеру можно скормить хоть "что угодно", хоть даже null – и он просто вернет Boolean.FALSE без вылета какого-либо исключения.

Вот почему строка Х в нашем примере не бросает исключение и присваивает переменной boo значение Boolean.FALSE. Следовательно, вариант A не верный.

Теперь давайте займемся поведением оператора if. Мы знаем, что тестируемое выражение обязано иметь тип boolean. Привыкнув к механизму автоупаковки и распаковки, мы ожидаем, что Boolean-объект будет транспарентно распакован в подстилающий примитив. Так оно и случится, поэтому код скомпилируется – но из-за того, что наш экзамен рассчитан на Java11; до появления автоупаковки в Java5 эта же строчка вызвала бы синтаксическую ошибку. Впрочем, в нашей задаче вообще нет такого варианта.

После распаковки булевый тест получит значение false и, стало быть, оператор печати не исполнится. Что ж, выходит, вариант D – единственный правильный.

А теперь давайте задумаемся над тем, что было бы, если бы булевый тест дал значение true.

Как мы знаем, Java предоставляет две идиомы сравнения. Одна из них является конструкцией, встроенной непосредственно в лексику языка: это оператор ==. Вторая идиома – а именно, метод equals(Object o) – предоставлена стандартной библиотекой и, будучи частью функционала класса java.lang.Object, доступна любому объекту. Она не делает ничего полезного и своим поведением не отличается от оператора "double equals", поэтому классам-наследникам предписывается по-своему решать, каким образом переопределить такое поведение. Метод equals() имеет интересный контракт из пяти пунктов, но в нашем примере он не используется, поэтому мы не будем обсуждать его; вместо этого давайте займемся оператором ==.

Мы знаем, что "double equals" принимает два операнда, точнее два выражения. Нюанс в том, что выражения могут иметь разные типы – и это различие сказывается на результате сравнения самым радикальным образом.

Что за разные типы? Это наши старые знакомые: примитивы (коих в Java восемь: boolean, byte, short, char, int, long, float и, наконец, double), либо то, что мы именуем термином ссылка (reference). Напомним, что ссылка в Java напоминает указатель (pointer), который показывает, где именно в памяти расположен тот или иной объект.

Если выражение выражение имеет примитивный тип, то это бинарная репрезентация некоего числа, например, 0b101010, то есть, десятичное 42. Это число будет записано в стеке и ему будет присвоена некая метка, которую мы привыкли называть словом "переменная". Но вот если речь идет не про примитив 42, а про Integer-объект, который инкапсулирует подстилающий примитив 42, то в стеке будет сидеть уже не 0b101010, а нечто куда более "вихрастое", например, 0xffff5637. Эта комбинация шестнадцатиричных литералов по сути является значением ссылки на объект, который в языке Java живет не в стеке, а в т.н. динамически аллоцируемой памяти, в знаменитой "куче" (heap). К примеру, в языке C/С++, прородителе Java, значением пойнтера является адрес объекта. В Java ситуация несколько сложнее, но в первом приближении мы тоже можем сказать, что значением ссылки (которая живет в стеке) является адрес объекта (который, напомним, живет на heap'е). Что в итоге? Пусть оператор "double equals" сравнивает значения двух переменных. Если это примитивы, JVM сравнит их бинарные значения, то есть – числа. Если это ссылки, то JVM сравнит их значения, но ведь значением ссылки является адрес того объекта, на который данная ссылка указывает. Вот почему принято говорить, что оператор == проверяет эквивалентность примитивных значений, а в случае ссылок он сравнивает уже идентичность объектов. Если у двух ссылочных переменных (например, класса Integer) одно и то же значение, мы имеем дело с одним и тем же объектом (один и тот же адрес!), но если объектов два, то они расположены по разным адресам. В этой ситуации оператор == вернет false.

Сейчас не должно вызывать удивление, что данный код:

photo_2023-06-05_13-58-36.jpg

обязательно покажет false: ведь успешный вызов конструктора через new, как мы уже упоминали, приведет к рождению очередного объекта. Простое правило на нашем экзамене: сколько видим слов new, как минимум столько же будет объектов. Стало быть, переменные v1 и v2 по необходимости ссылаются на разные объекты, и сравнение их адресов оператором == даст нам false.

А вот небольшая вариация на эту же тему: пусть у нас такой код:

уцкуц.jpg

Опять мы видим new и это означает, что у нас вновь два разных объекта: один родился благодаря стараниям конструктора, а второй прилетел к нам из статического фабричного метода, который был вызван имплицитно и полностью для нас транспарентно был вызван механизмом автоупаковки.

В заключение следует отметить, что фабрики для немутирующих объектов часто пишутся так, чтобы возвращать все тот же объект, если в метод были переданы те же аргументы. В частности, в документации на java.lang.Integer API мы видим следующую ремарку о методе valueOf(int):

“This method will always cache values in the range -128 to 127, inclusive, and may cache other values outside of this range.”

Другими словами, следующий кодовый сниппет:

Integer v1 = Integer.valueOf(1);

Integer v2 = Integer.valueOf(1);

System.out.print(v1 == v2);

даст нам true.

Официально задокументированная гарантия присутствует лишь для метода valueOf(int), хотя на практике valueOf(String)также демонстрирует это же поведение: Integer-объекты в пределах диапазона байта помещаются в константный пул.

Подведем итоги: поскольку код пользуется механизмом автоупаковки (в форме вызова Integer.valueOf(int)для создания одного объекта, а для второго применяет вызов конструктора, это означает, что если бы отработал оператор печати, мы бы увидели false. Поэтому правильным вариантом ответа остается D, о чем мы уже упоминали.

Последние статьи в блоге

ИИ-агенты в ERP-системах: каковы глобальные тренды и каким путем идет Россия

Ведущие ERP-вендоры переводят ИИ в режим автономных операций. В России этот сценарий пока не реализуется: западные вендоры ушли, облачные ИИ-релизы недоступны, регуляторы требуют переходить на суверенный контур и локальные LLM. О развитии рынка и стратегиях для бизнеса — в материале IT-World.

Новости
11 августа 2026

Саммари вебинара «ИИ-инструменты в работе архитектора ПО»

Дмитрий Овчаренко, технический директор с 15-летним опытом в архитектуре ПО, на сквозном примере стартапа — платформы для кондитеров — показал, как ИИ помогает архитектору ускорить работу на всех этапах: от чистого листа до готовых артефактов для команды.

Новости
07 августа 2026

Контроль качества ИИ-систем: от теории к практике

На результаты внедрения искусственного интеллекта в компаниях влияет сложный комплекс факторов. Для получения эффективного решения необходим контроль его качества и устранение узких мест на протяжении всей работы над проектом. О том, как этого добиться, рассказали заместитель директора центра перспективных разработок IBS Денис Воденеев и старший аналитик группы Data Science IBS Илья Гайдуков.

Новости
05 августа 2026

Саммари вебинара «Искусственный интеллект для бизнес-аналитика. Автоматизация для усиления экспертизы»

Максим Охманюк, эксперт с 25-летним опытом в IT, бизнес-анализе и управлении проектами, разобрал, как ИИ становится инструментом усиления аналитика, а не его заменой.

Новости
31 июля 2026

Как мы проектировали систему оценки ИТ-персонала для федерального ритейлера

В Учебном центре IBS мы разрабатываем методологию оценки персонала под задачи конкретного клиента. В крупной федеральной розничной сети с десятками ИТ-ролей и разрозненными критериями уровней специалистов это потребовало создания единой системы с нуля. Рассказываем, как это было.

28 июля 2026

Будущее разработки ПО: от кода к оркестрации агентов

Мультимодальные интерфейсы, внедрение ИИ-инструментов, новые подходы к анализу данных и принятию решений в компаниях уже активно меняют процесс разработки программного обеспечения. О том, как может эволюционировать создание ПО в недалеком будущем, рассказал Максим Ковтун, управляющий партнер «Разработка и тестирование» IBS.

Новости
23 июля 2026

IBS запускает независимую сертификацию для тестировщиков ПО

Центр сертификации IBS инициировал новую программу независимой оценки квалификации для тестировщиков программного обеспечения. Сертификация IBS позволяет ИТ-специалистам систематизировать знания, подтвердить соответствие единому стандарту качества и повысить конкурентоспособность на рынке труда.

21 июля 2026

Внедрение BI-систем: почему проект может не дать результатов

Реализация системы бизнес-аналитики (BI) может пройти технически гладко, но не принести ожидаемого эффекта компании. Причина обычно не в самой платформе, а в организации работы над проектом. Начальник отдела витрин данных и аналитики IBS Анна Филиппова поделилась взглядом на то, почему возникают такие ситуации и как их избежать.

17 июля 2026

Саммари вебинара «Проектирование высоконагруженной системы на примере агрегатора авиабилетов»

Алексей Додонов, эксперт с 20-летним опытом в ИТ, на сквозном кейсе разобрал эволюцию архитектуры стартапа по продаже авиабилетов — от монолита до распределённой системы, и как команда решала проблемы производительности на каждом этапе.

16 июля 2026

Бесплатный вебинар «Результативный ИИ в бизнесе: как внедрять безопасно, измеримо и с реальной пользой»

Искусственный интеллект — это уже не просто тренд, а рабочий инструмент. Но как перейти от пилотов и экспериментов к системному процессу с понятными метриками и управляемыми рисками?

Новости
03 июля 2026

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

Внедрение ИИ в корпоративную среду стало рутинной задачей для многих ИТ-директоров и руководителей проектов. Однако первые волны оптимизма уже столкнулись с суровой реальностью.

Жизнь компании
18 июня 2026

Саммари вебинара «Техсобес на Java: как системный подход и работа с ИИ превращают стресс в оффер»

Владимир Низов, технический директор с 10-летним стажем и эксперт Учебного центра IBS, рассказал, почему кандидаты проваливают технические интервью и как этого избежать. Отдельно разобрал работу с ИИ. Главное: заучивать тысячи страниц не нужно. Достаточно освоить индексный подход и единый паттерн системного дизайна. А ИИ воспринимать как инструмент с чёткими ограничениями.

Новости
09 июня 2026

Опыт развертывания корпоративной/ведомственной ИИ-инфраструктуры

Разговор о проблемах развертывания ИИ-инфраструктуры часто ведется на макроуровне: дефицит вычислительных мощностей, стоимость ускорителей, зависимость от внешних поставщиков, регуляторные ограничения. Все это важно, но если посмотреть на ситуацию глазами специалиста, которому предстоит решить эту задачу, вопрос становится более прикладным: как развернуть корпоративную ИИ-инфраструктуру, чтобы она не превратилась в дорогой, трудноуправляемый и слабо загруженный набор серверов?

Новости
02 июня 2026

«Аниматор с провалами памяти»: 6 ограничений ИИ, которые не дают вам писать качественный код

Вы когда-нибудь просили ИИ написать метод на Spring Boot, получали красивый, идеально отформатированный код, а он не работал? Потом вы копали глубже и находили, что нейросеть использовала RestTemplate вместо WebClient, забыла про @Transactional, а в методе с @PreUpdate пыталась изменить данные, которые уже ушли в SQL. И вы думали: «Ну, нейросеть же глупая». Нет. Не глупая. Она просто пишет код не как человек.

Новости
28 мая 2026

Роль и место России в мировой гонке в сфере ИИ

По масштабу амбиций и геополитическому значению гонку в сфере искусственного интеллекта все чаще сравнивают с космической гонкой эпохи холодной войны. Соревнование разворачивается одновременно по нескольким осям: вычислительные мощности, данные, кадры, модели и регулирование. В настоящее время ни одну из мировых держав нельзя назвать ведущей по всем направлениям, что оставляет возможность для разных подходов и стратегий в достижении лидерства. О положении России в этом глобальном соревновании, ее стратегических целях, инфраструктурных ограничениях и потенциале для развития рассказывает Денис Воденеев, заместитель директора центра перспективных разработок IBS.

Новости
21 мая 2026

Систематизация ИИ-компетенций: курсы под роли, карты эффективности и модули в комплексных программах

Учебный центр IBS систематизировал подход к развитию навыков работы с искусственным интеллектом. Хаотичное использование нейросетей, как показала практика, не даёт измеримого эффекта. Новое направление построено так, чтобы ИИ решал конкретные бизнес-задачи, а не просто ускорял рутину.

Новости
18 мая 2026

Как защитить бизнес и данные при внедрении ИИ

Искусственный интеллект способен резко расширить возможности развития бизнеса, однако просчеты при внедрении подобных систем могут обернуться серьезными убытками.

Новости
13 мая 2026

Искусственный архитектор: как нейросети справляются с проектированием ПО

В этой статье расскажем про большие языковые модели в приложении к работе архитектора ПО. Вместе мы посмотрим, насколько хорошо GPT понимает ИТ-архитектуру и сможет ли уже сегодня заменить архитектора. Пора разобраться, насколько глубоко ИИ может встроиться в рабочие процессы архитектора ПО — и стоит ли ему там оставаться.

Новости
24 апреля 2026

Бабушка с долгом в полмиллиона, однопоточное ядро и другие грабли: как не повторить чужие архитектурные ошибки

Любая система рано или поздно проверяется на прочность: нагрузкой, ростом бизнеса или человеческим фактором. Именно в эти моменты всплывают решения, которые казались безобидными на старте. Ниже — реальные кейсы из практики, где небольшие архитектурные допущения со временем превращались в ощутимые проблемы. Разберем, какие сигналы можно было заметить сразу и что стоит учитывать, чтобы не повторить эти сценарии в своих проектах.

Новости
16 апреля 2026

Как защитить информацию в приложениях, использующих ИИ

Представим, что системы контроля и анализа транзакций в банке начинают игнорировать 30% мошеннических операций. Система управления энергосетью выводит из строя ключевой узел подачи электроэнергии в город. Чат-бот службы поддержки начинает массово раскрывать персональные данные клиентов. К сожалению, это новая реальность, с которой может столкнуться любая компания, интегрирующая ИИ-системы в бизнеспроцессы.

Новости
08 апреля 2026

Нужна помощь? Оставьте заявку, и мы свяжемся с вами в ближайшее время

Согласен получать на e-mail информационные рассылки о новостях Учебного центра IBS
Корпоративное обучение Бесплатные семинары Оценка персонала Сертификация О нас Стать тренером Блог Личный кабинет
Пользователь только что записался на курс ""
Спасибо!
Форма отправлена успешно.