Java Guru 🤓
13.3K subscribers
928 photos
15 videos
779 links
Канал с вопросами и задачами с собеседований!

По сотрудничеству и рекламе: @NadikaKir

Канал в перечне РКН: https://vk.cc/cJrSQZ

Мы на бирже: telega.in/channels/javatasks/card?r=lcDuijdm
Download Telegram
Какая разница между @⁠Controller и @⁠RestController?

Controller – это один из стереотипов Spring Framework. Компоненты такого типа обычно занимаются обработкой сетевых запросов. Контроллер состоит из набора методов-обработчиков, помеченных аннотацией @RequestMapping.

Ответ на запрос можно сформировать разными способами: например просто вернуть из обработчика строку с именем jsp-файла, или же вернуть ResponseBodyEmitter, который будет асинхронно заполняться данными позже. Все возможные варианты перечислены в документации.

Большинство современных API реализуется по архитектуре REST. В ней каждая сущность доступна под собственным URI. В методе-обработчике возвращается экземпляр класса этой сущности, который преобразуется в ответ сервера одним из HttpMessageConverter-ов. Например, в JSON его превратит MappingJackson2HttpMessageConverter. Чтобы использовать этот способ ответа, метод, или весь контроллер, должен иметь аннотацию
@ResponseBody.

@RestController – это просто сокращенная запись для @Controller + @ResponseBody.

Java Guru🤓 #java
🔥7👍64👌2
Как вызвать транзакционный метод из того же класса?

В Spring Framework существует аннотация @Transactional. Ей помечается метод или класс, весь код которого должен выполняться в рамках транзакции. Обычно имеется в виду транзакция базы данных, но вообще это понятие определяется используемым transactionManager-ом. Настройки, такие как уровень изоляции, стратегия роллбэка и прочие, определяются через параметры этой аннотации.

В теории,
@Transactional делает метод транзакционным для этого класса и всех его наследников. На практике же, по умолчанию, если вызвать транзакционный метод Foo.bar() из Foo.baz(), то транзакция не создастся.

Это происходит вследствие того, что по умолчанию Spring AOP добавляет код открытия/закрытия транзакции через динамический proxy класс. То есть, вместо Foo инджектится нечто, похожее на код на изображении.

Первый вариант решения проблемы – вместо аннотации использовать TransactionTemplate, то есть обернуть код в транзакцию вручную. Примеры использования можно посмотреть в
этой статье.

Другой, более универсальный, но более сложный в конфигурации способ – переключить режим работы Spring AOP с динамических прокси на нечто другое. Обычно применяется библиотека AspectJ:

@EnableTransactionManagement(mode = AdviceMode.ASPECTJ)


В Spring AOP есть понятие weaving – этап добавления дополнительной функциональности (аспектов). В нашем случае, это код открытия/закрытия транзакции. Чтобы заработал weaving AspectJ этапа компиляции, в сборку нужно добавить плагин: aspectj-maven-plugin для maven, gradle-aspectj для gradle.


Java Guru🤓 #java
👍10🔥53
Опишите жизненный цикл Spring Bean

Beans – центральный объект заботы Spring Framework. За кулисами фреймворка с ними происходит множество процессов. Во многие из них можно вмешаться, добавив собственную логику в разные этапы жизненного цикла. Через следующие этапы проходит каждый отдельно взятый бин:

1. Инстанцирование объекта. Техническое начало жизни бина, работа конструктора его класса;

2. Установка свойств из конфигурации бина, внедрение зависимостей;

3. Нотификация aware-интерфейсов. BeanNameAware, BeanFactoryAware и другие. Мы уже писали о таких интерфейсах ранее. Технически, выполняется системными подтипами BeanPostProcessor, и совпадает с шагом 4;

4. Пре-инициализация – метод postProcessBeforeInitialization() интерфейса BeanPostProcessor;

5. Инициализация. Разные способы применяются в таком порядке:
• Метод бина с аннотацией
@PostConstruct из стандарта JSR-250 (рекомендуемый способ);
• Метод afterPropertiesSet() бина под интерфейсом InitializingBean;
• Init-метод. Для отдельного бина его имя устанавливается в параметре определения initMethod. В xml-конфигурации можно установить для всех бинов сразу, с помощью default-init-method;

6. Пост-инициализация – метод postProcessAfterInitialization() интерфейса BeanPostProcessor.
Когда IoC-контейнер завершает свою работу, мы можем кастомизировать этап штатного уничтожения бина. Как со всеми способами финализации в Java, при жестком выключении (kill -9) гарантии вызова этого этапа нет. Три альтернативных способа «деинициализации» вызываются в том же порядке, что симметричные им методы инициализации:

1. Метод с аннотацией
@PreDestroy;
2. Метод с именем, которое указано в свойстве destroyMethod определния бина (или в глобальном default-destroy-method);
3. Метод destroy() интерфейса DisposableBean.

Не следует путать жизненный цикл отдельного бина с жизненным циклом контекста и этапами подготовки фабрик бинов. О них мы поговорим в будущих публикациях.


Java Guru🤓 #java
👍156🔥3😐1
Как контролировать и управлять приложениями на Spring Boot без лишней головной боли?

На открытом вебинаре «Spring Boot Actuator: основы мониторинга и управления приложением» 25 июня в 20:00 МСК мы разберём:

- Для чего нужен Spring Boot Actuator.
- Как настроить и использовать метрики для контроля приложений.
- Как избежать проблем с производительностью на ранних этапах разработки.

Представьте, что вы с лёгкостью настраиваете мониторинг, отслеживаете метрики и эффективно управляете приложениями без перерывов в работе. Это станет возможным, если освоить Spring Boot Actuator.

Открытый урок проходит в преддверии старта курса «Разработчик на Spring Framework» — все участники получат скидку на обучение.

Регистрируйтесь прямо сейчас: https://vk.cc/cN430J

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
2👍2🔥2
Как использовать JavaEE сервлет в Spring Framework?

Web-приложение на Spring MVC технически само по себе работает на сервлетах: всю обработку запросов берет на себя единый DispatcherServlet. С его помощью реализуется паттерн Front Controller.

Если вам нужно определить в программе полностью независимый от Spring-контекста сервлет или фильтр, ничего особенного для этого делать не нужно. Как обычно в Servlet API, нужно объявить класс, добавить его в web.xml как сервлет, добавить для сервлета маппинг.

Сервлет живет вне Spring-контекста, внедрение зависимостей в нём просто так не заработает. Чтобы использовать autowiring, на этапе инициализации сервлета вызывается статический SpringBeanAutowiringSupport.processInjectionBasedOnServletContext, с текущим сервлетом и его контекстом в аргументах. В этом же утилитарном классе есть ряд других средств для работы с контекстом извне.

Если программа построена на Spring Boot, создание бина типа ServletRegistrationBean поможет добавить сервлеты в рантайме. А для декларативного добавления на этапе компиляции, к классу конфигурации применяется
@ServletComponentScan. С этой аннотацией стартер приложения просканирует и добавит в контекст все web-компоненты в стиле Servlet 3.0: классы с аннотациями @WebFilter, @WebListener и @WebServlet.

Java Guru🤓 #java
🔥63👍3
👩‍💻🎯 Юнитесты на Java: как новичку поймать баги за 5 Секунд?

Приглашаем на открытый урок.

🗓 25 июня в 20:00 МСК
🆓 Бесплатно. Урок в рамках старта курса «Java-разработчик».

🦾 Тестирование — суперсила разработчика. Научитесь писать код, который проверяет сам себя, экономит часы на отладке и делает ваши приложения неуязвимыми.

О чём поговорим:
✔️ Что такое Unit-тесты? Для чего они нужны, даже если «код и так работает».
✔️ JUnit 5 для новичков: как установить и написать первый тест.
✔️ Тестирование = Дзен-кодинг: как тесты помогают понять свой код лучше вас самих.
✔️ Ловушки и лайфхаки: что делать, если тесты падают?

Кому будет интересно:
Начинающим Java-разработчикам, студентам и всем, кто хочет перестать бояться слов «тестирование» и «баги».

В результате вебинара вы:
Создадите свой первый тест на Java, поймёте, как тестировать методы с исключениями, и начнёте писать код, которым можно гордиться.

🔗 Ссылка на регистрацию: https://vk.cc/cN43yY

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Please open Telegram to view this post
VIEW IN TELEGRAM
👍32🔥2
В чём преимущества и недостатки Spring Boot?

Основные сущности фреймворка Spring Boot – это стартеры. Зависимости с названиями вида spring-boot-starter-xxx выполняют две основных задачи. Во-первых, они добавляют набор типичных сторонних библиотек-зависимостей; во-вторых, регистрируют типичные бины и их конфигурации. Кроме того, со Spring Boot в проекте появляется ряд таких полезностей, как embedded-сервер, конфигурация web-приложения без web.xml, метрики, properties вынесенные из кода во внешние файлы.

Например, spring-boot-starter-data-jpa даст вам готовый комплект всего необходимого для использования JPA: драйвер, совместимую с ним версию Hibernate, библиотеки Persistence API и Spring Data. В контексте приложения появятся все нужные для JPA репозиториев бины.

Таким образом Spring Boot ускоряет и упрощает разработку, дает возможность избавиться от boilerplate-кода в проекте и сфокусироваться на бизнес-задачах. Это бывает особенно важно в микросервисной архитектуре, когда создается большое количество приложений.

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


Java Guru🤓 #java
🔥10👍74
Как работает инъекция прототипа в синглтон?

Раньше мы уже
рассматривали различия скоупов singleton и prototype в Spring Framework. Допустим ситуацию, когда в singleton-компонент внедряется зависимость со скоупом prototype – когда будет создан её объект?

Если просто добавить к определению бина аннотацию
@Scope(SCOPE_PROTOTYPE), и использовать этот бин в синглтоне через аннотацию @Autowired – будет создан только один объект. Потому что синглтон создается только однажды, и обращение к прототипу случится тоже однажды при его создании (при внедрении зависимости).

Примитивный способ получать новый объект при каждом обращении – отказаться от
@Autowired, и доставать его из контекста вручную. Для этого нужно вызывать context.getBean(MyPrototype.class).

Воспользоваться автоматическим внедрением зависимостей можно через внедрение метода (паттерн «Команда»). Автовайрится не сам объект, а производящий его метод.

Более красивый декларативный способ – правильно настроить определение бина. В аннотации
@Scope кроме самого scopeName доступен второй параметр – proxyMode. По умолчанию его значение NO – прокси не создается. Но если указать INTERFACES или TARGET_CLASS, то под @Autowired будет внедряться не сам объект, а сгенерированный фреймворком прокси. И когда проксируемый бин имеет скоуп prototype, то объект внутри прокси будет пересоздаваться при каждом обращении.

Java Guru🤓 #java
👍16🔥74❤‍🔥1
Перечислите методы класса java.lang.Object

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

🔘public final native Class<?> getClass()
🔘public native int hashCode()
🔘public boolean equals(Object obj)
🔘protected native Object clone() throws CloneNotSupportedException
🔘public String toString()
🔘public final native void notify()
🔘public final native void notifyAll()
🔘public final native void wait(long timeout) throws InterruptedException
🔘public final void wait(long timeout, int nanos) throws InterruptedException
🔘public final void wait() throws InterruptedException
🔘protected void finalize() throws Throwable


Java Guru🤓 #java
Please open Telegram to view this post
VIEW IN TELEGRAM
8👍6🔥4
🦾👩‍💻 Вы опытный Java-разработчик и хотите углубить свои знания? Понимание JVM, профилирование и оптимизация приложений под нагрузкой — это ключевые навыки для карьерного роста.

⚡️ Курс «Java Developer. Advanced» от OTUS даст вам все необходимые знания для оптимизации приложений в облачной инфраструктуре.

На курсе вы изучите:

✔️ Принципы профилирования JVM и оптимизации приложений.
✔️ Выбор и настройку сборщика мусора (GC).
✔️ Использование фреймворков для неблокирующих IO.
✔️ Интеграцию с Prometheus и Grafana для мониторинга.
✔️ Разработку микросервисов и деплой в Kubernetes.

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

➡️ Пройдите короткий тест и присоединяйтесь к группе: https://vk.cc/cNbevy

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Please open Telegram to view this post
VIEW IN TELEGRAM
2👍2🔥2
toString

Строковое представление экземпляра. По умолчанию возвращает "ПолноеИмяКласса@хэшВ16тиричномВиде" (например "java.lang.Object@1a23b4f"). Часть после @ – не адрес в памяти, так что умолчательная реализация почти не несет практической пользы. Полезно добавлять нормальную реализацию даже если не необходимо в логике программы – поможет в отладке. Готовый вызов x.toString() с проверкой на null уже реализован в String.valueOf(x).
👍11🔥52
Какие бывают строковые классы?

Кроме очевидного класса String, в стандарте Java существует еще StringBuffer и StringBuilder. Класс String иммутабелен, а эти два вспомогательных класса реализуют для него паттерн Builder и служат способом редактирования строки без относительно дорогого пересоздания объекта.

Все методы StringBuffer синхронны. В Java 1.5 ему на замену пришел несинхронизированный вариант StringBuilder. Эта ситуация аналогична HashMap и Hashtable. В остальном эти два класса почти ничем не отличаются, имеют одинаковый набор методов и конструкторов.

Для буфера и билдера не работает синтаксический сахар строк:
🔘Их нельзя создать литералом, вместо этого используется обычный конструктор;
🔘Нельзя конкатенировать оператором +, вместо этого используются обычные методы insert и append.

Сам оператор конкатенации константных выражений, компилируется в интернированную строку, но для не-констант неявно использует StringBuilder.


Java Guru🤓 #java
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11🔥43
👩‍💻 Разработка на Java требует глубокого понимания не только языка, но и принципов работы JVM, многопоточности и современных фреймворков.

🎯 Курс «Java Developer. Professional» — это структурированное обучение для разработчиков, которые хотят выйти на новый уровень, освоить актуальный стек технологий и уверенно претендовать на позиции уровня Middle+.

Вы получите 96 часов практической работы, на живых вебинарах разберете ключевые аспекты работы JVM, научитесь строить эффективные многопоточные приложения, освоите Spring WebFlux, Kafka, реактивный Postgres и Kubernetes.

📚Программа OTUS постоянно обновляется, соответствуя требованиям рынка, а диплом ценится работодателями.

➡️ Пройдите вступительное тестирование и присоединяйтесь к группе: https://vk.cc/cNd7K9

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Please open Telegram to view this post
VIEW IN TELEGRAM
2👍2🔥2
Как обойти строчку?

Для хранения строк в Java в общем случае используется кодировка UTF-16. Для полного понимания вопроса необходимо понимать ее особенности: что такое суррогатные пары и плоскости юникода. Конкретнее, что один символ в обычном понимании слова называется code point, и представляется одним или двумя значениями типа char. Значит, корректный ответ нужно начать с уточнения: подразумевается ли обход значений char или code point.

Из этого следует, что и длина строки, верхняя граница итерации – тоже понятие неоднозначное. Метод length() на самом деле возвращает не количество Unicode-символов, а количество значений char. Реальную логическую длину (количество кодовых точек) покажет метод codePointCount(). Нужно помнить, что чтобы обнаружить суррогатные пары, внутри ему придется проитерировать по символам.

Итерироваться по char можно либо получая по одному символу с помощью метода charAt(), либо со всем массивом сразу, методом toCharArray(). В случае с массивом создается копия внутреннего значения – это естественно медленнее, зато этот массив-копию можно мутировать. Работать с суррогатными парами придется вручную, для этого в классе Character есть специальные методы.

Другой вариант – сразу оперировать методами codePointAt() и codePointBefore(). Параметром указываются индексы массива char, но результатом будут кодовые точки типа int.

В Java 8 появился новый удобный способ обхода – методы chars() и codePoints(). Они возвращают IntStream из символов и кодовых точек соответственно. Носителем результирующих стримов выступает оригинальное внутреннее значение строки, копирование массива не требуется.


Java Guru🤓 #java
👍10🔥65
Из чего состоит String?

Ответ как обычно зависит от версии Java. Два поля, которые присутствовали во всех версиях – массив символов char[] value и int hash. В поле hash кэшируется хэш-сумма при первом подсчете для соблюдения контракта метода hashCode.

До Java 7 были еще поля offset и count – чтобы переиспользовать без пересоздания массивы из билдеров и других строк. В современной джаве от этого отказались в угоду меньшего потребления памяти.

Изначально все строки хранились в кодировке UTF-16, каждый символ занимал по два байта и умещался в char. Однако выяснилось, что статистически большинство строк содержит только ASCII-символы, которые вмещаются в один байт и составляют кодировку LATIN-1. То есть старший байт в большинстве char остается нулевым, и строки наполовину состоят из пустоты. А примерно четверть памяти приложений состоит из одних только строк.

В Java 6 была введена экспериментальная фича Compressed Strings – способность строки хранить строки в LATIN-1 в массиве byte вместо char. С этой фичей был ряд проблем, и позднее ее убрали.

Снова сжатие строк появилось в Java 9 – теперь оно называется Compact Strings и включено по умолчанию. В классе String появилось поле coder, которое переключает кодировки, и статический флаг COMPACT_STRINGS, выключающий фичу вообще. Тип массива value окончательно изменился с char[] на byte[].


Java Guru🤓 #java
🔥165
Как применить регулярное выражение в Java?

Регулярные выражения – мощный механизм работы со строками. Здесь мы не будем говорить о регулярных выражениях в целом, поговорим об их использовании в Java. Это становится возможно благодаря пакету java.util.regex стандартной библиотеки.

Работа с регулярными выражениями в Java начинается с класса Pattern. Это представление самого выражения, без привязки к целевому тексту. Создать его можно компиляцией строки, с помощью фабричного метода Pattern.compile(). Паттерн иммутабельный и потокобезопасный.

Matcher – регулярное выражение, примененное к конкретному тексту. Пораждается вызовом метода Pattern.matches(). Одним паттерном можно порождать несколько разных матчеров. В отличие от паттерна, матчер мутирует. Он не безопасен для многопоточной среды. Основные операции регулярных выражений – перебор совпадений, доступ к группам, замена – реализованы именно в этом классе.

Работа с экземпляром Matcher похожа на работу с итератором. Результат метода matches() просто скажет, соответствует ли строка шаблону. Но после его вызова матчер поменяет состояние. Теперь, из него можно получить группы, позицию совпадения в тексте, а также произвести замену.

В объекте шаблона Pattern реализованы несколько методов-сокращений, чтобы не использовать Matcher явно. Например, просто проверить строку на соответствие выражению можно одним методом Pattern.matches().


Java Guru🤓 #java
8👍6🔥4
👩‍💻🎯 Открытый урок «Основы многопоточности в Java».

🗓 7 июля в 20:00 МСК
🆓 Бесплатно. Урок в рамках старта курса «Java-разработчик».

Приглашаем вас на бесплатный вебинар, посвященный основам многопоточности в Java. Абсолютное большинство коммерческих Java-приложений работает в многопоточном режиме, и понимание принципов многопоточной обработки позволяет писать более эффективные программы, избегая распространенных ошибок. На занятии мы разберем ключевые подходы к многопоточности, изучим используемые классы, а также рассмотрим типовые проблемы и их решения.

Программа урока:
✔️ Введение в многопоточность: что это и зачем это нужно.
✔️ Изучение базовых классов для работы с потоками.
✔️ Разбор типовых проблем многопоточности и подходов к их решению.

Урок будет полезен тем, кто хочет:
- Разобраться в основах многопоточности в Java.
- Понять, как писать многопоточные программы.
- Узнать, какие классы используются для работы с потоками в Java.

В результате урока вы:
- Поймете подходы к многопоточности в Java.
- Изучите базовые классы и синтаксис многопоточной обработки.
- Сможете применять полученные знания для создания более эффективных Java-приложений.

🔗 Ссылка на регистрацию: https://vk.cc/cNjyOU

Реклама. ООО «Отус онлайн-образование», ОГРН 117774661857
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥42👍2
Как разбить строку на слова?

StringTokenizer – специально предназначенный для этого класс стандартной библиотеки Java. Ему нужно задать разделители, по ним строка будет разделена на «токены». Это устаревший класс, он остается в библиотеке только для обратной совместимости.

Вместо него рекомендуется использовать метод String.split(). Метод принимает строку с регулярным выражением, и опциональный лимит токенов. Реализация особенно оптимизирована для односимвольного разделителя. Но следует помнить, что даже если символ один, это всё ещё регулярное выражение – спецсимвол должен экранироваться.

Другой подходящий метод – Pattern.split(). Он, наоборот, вызывается у регулярного выражения, а принимает целевую строку. В этот же метод делегируется и выполнение String.split(). Этот способ предпочтительнее, когда в регулярном выражении больше одного символа, а скомпилированный паттерн применяется повторно.


Java Guru🤓 #java
👍74🔥3
🔍 Завтра тестовое собеседование с Java-разработчиком

2 июля(уже завтра!) в 19:00 по мск приходи онлайн на открытое собеседование, чтобы посмотреть на настоящее интервью на Middle Java-разработчика.

Как это будет:
📂 Сергей Чамкин, старший разработчик из Uzum, ex-WildBerries, будет задавать реальные вопросы и задачи разработчику-добровольцу
📂 Cергей будет комментировать каждый ответ респондента, чтобы дать понять чего от вас ожидает собеседующий на интервью
📂 В конце можно будет задать любой вопрос Сергею

Это бесплатно. Эфир проходит в рамках менторской программы от ШОРТКАТ для Java-разработчиков, которые хотят повысить свой грейд, ЗП и прокачать скиллы.

Переходи в нашего бота, чтобы получить ссылку на эфир → @shortcut_sh_bot

Реклама. ООО "ШОРТКАТ", ИНН: 9731139396, erid: 2VtzquvmY4P
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥32👍2