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

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

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

Мы на бирже: telega.in/channels/javatasks/card?r=lcDuijdm
Download Telegram
👩‍💻 Ваши Java-приложения под нагрузкой едва дышат? Профилирование и оптимизация кода остаются за скобками?

Курс «Java Developer. Advanced» от OTUS — это глубокое погружение в устройство JVM, байткод, сборщики мусора, профилирование и оптимизацию в облаке.
Наши эксперты-практики покажут, как выбрать GC, снять дамп памяти и обнаружить утечки, как профилировать “горячие” места, настраивать интеграцию с Prometheus & Grafana и деплоить сервисы в Kubernetes.

🦾 Вы научитесь обосновывать выбор JVM-имплементации, анализировать heap-дампы, синхронизировать потоки, использовать Reactor и неблокирующие I/O, проектировать метрики и трассировку.

🎁 Дарим промокод, который дает скидку на обучение - JVADV7

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

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

Вопрос, который зачастую дается в виде практической задачи. Конечно, результата можно добиться разными способами: парой атомарных переменных, критическими секциями, потокобезопасными коллекциями. Но полезно знать, что специально для этого случая в стандартной библиотеке java.util.concurrent есть простой класс Exchanger.

Класс содержит единственный метод V exchange(V x). Один поток передает в него данные, и встает в ожидание. Ожидание завершается, когда второй поток также приходит в метод exchange со своей порцией информации. В качестве результата вызова потоки получают данные друг друга.

На основе класса Exchanger удобно создавать пайплайны обработки данных. Первый поток выполняет свою часть обработки, и складывает результаты в буфер. В качестве буфера может работать любой многоразовый объект-контейнер. Когда он заполняется, следующий поток обменивает его на второй, пустой буфер. Таким образом два буфера используются поочередно, не выделяется лишний раз память и не нагружается GC. Далее из попарно обменивающихся буферами потоков может строиться длинная многопоточная цепочка обработки.


Java Guru🤓 #java
6🔥4👍1
👇Паттерн Строитель (Builder)

Builder — это порождающий паттерн, который позволяет пошагово создавать сложные объекты. Вместо того чтобы создавать объект одним большим конструктором с множеством параметров, Builder организует процесс создания по частям, обеспечивая гибкость и читаемость кода.

Использование:

🟡 Когда нужно создать объект с большим количеством параметров, и не все из них обязательны.
🟡 Когда процесс создания объекта требует выполнения нескольких шагов или дополнительных проверок.
🟡 В случаях, когда один и тот же код должен создавать разные представления объекта (например, текстовое и графическое).

Преимущества:

1️⃣ Упрощает создание сложных объектов, делая процесс понятным и читаемым.
2️⃣ Позволяет создавать объекты с разными вариациями без необходимости дублирования кода.
3️⃣ Разделяет логику создания объекта от его структуры, что упрощает поддержку и модификацию кода.

Недостатки:

1️⃣ Увеличивает сложность кода за счёт создания дополнительных классов и методов.
2️⃣ Может быть избыточным для простых объектов с небольшим количеством параметров.
3️⃣ Требует дополнительного внимания при проектировании, чтобы избежать путаницы между обязательными и необязательными шагами.

📌 Паттерн Builder полезен, если объект имеет много параметров и их нужно задавать гибко. Например, при создании сложных конфигураций для HTTP-запросов (заголовки, тело, параметры), построении графических интерфейсов или генерации HTML-документов. Builder помогает сделать код более понятным и избежать создания конструкций с длинными и неудобными конструкторами.

@javatasks #java
Please open Telegram to view this post
VIEW IN TELEGRAM
8👍4🔥1
Что такое функциональный интерфейс?

Так называется специальная разновидность интерфейса, который определяет тип-функцию, коллбэк.

Чтобы компилятор считал интерфейс функциональным, этот интерфейс должен добавлять единственный абстрактный метод. Вдобавок он может содержать любое количество дефолтных методов с телом. Переобъявление методов класса Object также игнорируется.

Никаких других ограничений на метод не накладывается: он не ограничен в типах аргументов и возвращаемого значения, может иметь любое название и список выбрасываемых исключений (checked и unchecked).

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

Дополнительно функциональный интерфейс принято помечать аннотацией
@FunctionalInterface. Наличие этой аннотации не необходимо, но оно даёт дополнительную валидацию: её присутствие на нефункциональном типе спровоцирует ошибку компиляции.

Типичные примеры функциональных интерфейсов: Callable, Supplier, Comparable.


@javatasks #java
5🔥4👍2
Задачи с собеседований: Проверка, является ли бинарное дерево деревом поиска (middle)

— Как определить, является ли заданное бинарное дерево деревом поиска (BST)?

📌 Ключевые моменты:

- Бинарное дерево поиска (BST) — это бинарное дерево, в котором для каждого узла все значения в левом поддереве меньше значения узла, а все значения в правом поддереве больше.
- Для проверки можно использовать рекурсивный подход с отслеживанием допустимых диапазонов значений для каждого узла.
- Как изменить реализацию для работы с любыми типами данных в узлах дерева?

Реализация с числами в узлах на картинке 👆

@javatasks #java
Please open Telegram to view this post
VIEW IN TELEGRAM
7👍3🔥2
Чем отличается final finally finalize?

Тем, что это даже синтаксически разные вещи. Как и вопрос о методах Object, это способ начать разговор.

finalize – метод-финализатор из Object.

final – модификатор, который применяется к переменным, полям, методам и классам. Переменная или поле становится неизменяемым и требует инициализации. Финальный метод нельзя переопределить в наследниках. Финальный класс не может иметь наследников вообще. Используется для создания хорошего API по принципу наименьших привилегий.

Когда в методе используется локальная переменная внешней области видимости, она обязана быть
effectively final. В этом случае ключевое слово final необязательно, но значение всё равно не должно меняться.

finally – часть языковой конструкции try-catch-finally.

Любое исключение, выброшенное из блока try переводит исполнение в самый соответствующий ему catch (при наличии). Этим продиктована необходимость располагать блоки catch в строгом порядке, от типа исключения-наследника, к родителю. В случае multicatch тот же порядок должен соблюдаться и внутри одного catch.
Больше примеров про порядок.

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

Для требующих финализации классов («ресурсов») добавляется интерфейс AutoCloseable, повторяющийся код блока final выносится в метод close и вызывается неявно в конце
try-with-resources. Если в этой конструкции присутствует и явный final, он будет выполнен после.

Java Guru🤓 #java
6👍4🔥4
Чем отличаются checked и unchecked исключения?

Вопрос формулируют по-разному, суть вопроса – объяснение иерархии классов исключений. Подробно описано в документации.

Исключения бывают checked и unchecked. Checked требуется указывать в сигнатуре метода в разделе throws; перехватывать или добавлять в throws в вызывающем его методе. Unchecked можно добавить, но не обязательно, перехватывать не обязательно даже если указана в throws.

🔘Throwable – базовый класс для всего что может быть использовано с оператором throw и в конструкции try-catch
🔘RuntimeException – «нормальные» unchecked-исключения
🔘Error – unchecked исключения, которые означают «серьезные проблемы» приложения. Не должны обрабатываться (хотя технически можно). Теоретически JVM может находиться в невалидном состоянии и не давать больше никаких гарантий
🔘Exception (кроме RuntimeException) – checked исключения

@javatasks #java
Please open Telegram to view this post
VIEW IN TELEGRAM
5🔥4👍3
Зачем нужно ключевое слово default?

Изначально (с Java 1.5) это слово использовалось для объявления дефолтного значения элементов аннотации.

В Java 8 вместе с лямбдами и стримами появилась острая необходимость дополнить стандартные интерфейсы новыми методами. Никто естественно не собирался ломать обратную совместимость, и было предложено добавить методы по умолчанию.

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

В реализации такого метода его дефолтный вариант вызывается тем же синтаксисом, что и внешний класс из вложенного: InterfaceName.super.methodName().

Методы по умолчанию подошли еще на шаг к введению в Java беспроблемной версии множественного наследования – примесям (mixin). Интерфейс не может иметь состояния, поэтому полноценные примеси всё ещё недоступны.


@javatasks #java
👍7🔥41
В каком порядке указываются модификаторы?

Правила применения модификаторов поля описаны в JLS 8.3.1:
🔘Нельзя указывать один модификатор дважды;
🔘Нельзя использовать несколько модификаторов доступа одновременно.

Порядок указания вообще свободный, но обычно используется следующий:
@Аннотации, доступ,
static final transient volatile


Требования для модификаторов метода находятся в JLS 8.4.3:
🔘Те же требования, что и к полю;
🔘Совместно с abstract кроме аннотаций можно использовать только protected или public;
🔘native метод не может использовать strictfp.

И так же не требуется, но рекомендуется использовать такой порядок:
@Аннотации, доступ,
abstract static final synchronized native strictfp

Java Guru🤓 #java
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10🔥61
📎Паттерн Фасад (Facade)

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

Использование:

🟡 Когда система состоит из множества классов, и нужно упростить доступ к её функционалу.
🟡 Когда нужно предоставить клиенту единый интерфейс для работы с несколькими подсистемами.
🟡 Когда необходимо уменьшить зависимость между клиентом и сложной системой, скрыв внутренние детали реализации.

Преимущества:

1️⃣ Упрощает взаимодействие с комплексной системой, предоставляя удобный интерфейс.
2️⃣ Снижает зависимость клиента от конкретных классов подсистем, облегчая поддержку и тестирование.
3️⃣ Уменьшает количество точек взаимодействия с системой, что помогает избежать ошибок и повысить удобство работы.

Недостатки:

1️⃣ Может скрывать избыточную функциональность, ограничивая возможности системы.
2️⃣ Увеличивает количество кода за счёт добавления нового фасадного класса.
3️⃣ Если фасад слишком абстрактен, может стать сложным для понимания и поддержки.

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

Java библиотека #java
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥106👍2
Что такое короткое замыкание логического оператора?

Логические операторы || и && лево-ассоциативны, то есть их параметры вычисляются слева направо. Если первое значение оказалось true в || или false в && – конечный результат уже предрешен, он будет тем же. В этом случае происходит так называемое «короткое замыкание» (short-circuiting) – оставшийся второй аргумент не вычисляется за ненадобностью.

Эту особенность иногда удобно эксплуатировать, например для проверки на null в одну строку:
return param != null && param.getBoolMember();


Но иногда такая ситуация влечет за собой неожиданные плавающие баги, если второй аргумент – не переменная, а функция с побочным эффектом. Для этой ситуации введены версии операторов без короткого замыкания: | и &. Это логические вариации «битового и» и «битового или».

Вдобавок доступен оператор «исключающее или» ^. Он почти никогда не используется для булевых параметров, потому что абсолютно эквивалентен более интуитивно понятному !=. Другие битовые операторы для логических аргументов недоступны.


Java Guru🤓 #java
8👍4🔥1
👩‍💻 31 июля стартует курс «Java-разработчик» от OTUS — это то, что нужно, если вы хотите успешно вкатиться в разработку в 2025

🦾 Вас ждет огромное количество практики и реальные кейсы: настройка окружения, базовые алгоритмы, синтаксис Java, Spring и Docker. Мы покажем, почему диплом OTUS ценят HR в крупных компаниях.

Если вы сисадмин, тестировщик, аналитик или просто хотите освоить программирование с нуля — этот курс для вас.
Мы научим создавать серверные веб-приложения, работать с PostgreSQL, Kafka и Kubernetes, формировать портфолио и готовить резюме под Middle-Java-Dev.

🎁 Дарим промокод, который дает скидку на обучение - JAVA7

👉 Оставьте заявку и и присоединяйтесь к группе: https://vk.cc/cNTt7j

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

Во-первых, стоит освежить знания о бинарном представлении целых знаковых чисел. В Java используется подход two's complement – для значения 0 все биты нули, при переполнении максимального значения на 1 получается минимальное.

Бинарные битовые операторы &, | и ^ действуют очевидным образом: выполняют побитовые «И», «ИЛИ» и «исключающее ИЛИ» (XOR) соответственно. Здесь особенно интересен XOR:

Применение к значению «исключающего или» с одним и тем же параметром два раза дает то же значение. За счет этого его можно использовать как простейшее шифрование, аргумент выступит ключом;
С помощью XOR реализуется XOR-обмен – алгоритм обмена значениями переменных без дополнительной памяти и без риска переполнения. Это также один из популярных вопросов для собеседования.

Унарный оператор битового отрицания (дополнения) ~. Эквивалентен «исключающему или» с самим собой – все биты инвертируются. ~x эквивалентно -x-1. ~0 == -1.
Битовые сдвиги: левый << правый знаковый >> и правый беззнаковый >>>. Левый операнд – что сдвигать, правый – на сколько битов.

Второй параметр, дистанция сдвига, должен быть не больше доступных разрядов – 31 для int и 63 для long. Если передано значение больше – используются младшие 5 и 7 битов соответственно. То есть для int переменной x << 33 эквивалентно x << 2.

a << b эквивалентно умножению a на 2 в степени b.
a >> b совпадает с делением на 2 в степени b, с округлением вниз. Для положительных a то же что a/pow(2,b). Для не делящихся нацело на pow(2,b) отрицательных это a/pow(2,b)-1.

Беззнаковый сдвиг вправо трактует число не как two's complement, а как беззнаковое. То есть Integer.MIN_VALUE будет сдвинут так, как будто это сдвигается число на 1 большее чем Integer.MAX_VALUE.

Беззнакового сдвига влево не существует, потому что он совпадал бы со знаковым сдвигом, и был бы избыточным.


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

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

Как это будет:
📂 Алексей Ушаровский, разработчик с опытом работы в Oracle и EPAM, будет задавать реальные вопросы и задачи разработчику-добровольцу
📂 Алексей будет комментировать каждый ответ респондента, чтобы дать понять чего от вас ожидает собеседующий на интервью
📂 В конце можно будет задать любой вопрос Алексею

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

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

Реклама.
О рекламодателе
Please open Telegram to view this post
VIEW IN TELEGRAM
3👍2🔥2
Как узнать, является ли A подтипом B?

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

instanceof – бинарный оператор, самый быстрый и самый используемый. Если есть экземпляр A и можно указать B явно, выбирать надо его. Если A (точнее тип хранящей экземпляр A переменной) и B не из одной цепочки наследования – экземпляр точно не может быть подтипом B и компиляция упадет с ошибкой inconvertible types.

Class::isInstance – метод принимает параметром объект типа A. Его стоит выбрать, когда экземпляр A в наличии, но B – неизвестный на этапе компиляции тип. То есть, для переменных A a и Class bClass, можем проверить bClass.isInstance(a).

Class::isAssignableFrom – принимает Class<A>. Единственное, что остается, если экземпляра A нет. bClass.isAssignableFrom(aClass).

Есть еще четвертый способ – имея экземпляр типа A привести его к B. Если типы были несовместимы, приведение выбросит ClassCastException. Это во всех смыслах плохой способ, построению логики программы на исключениях нет оправдания. Подробная аргументация описана в Effective Java Item 57.


Java Guru🤓 #java
6👍5🔥3
Чем анонимный внутренний класс отличается от лямбды?

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

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

Лямбдой реализуется только функциональный интерфейс. Функциональный интерфейс – это тип с единственным абстрактным методом. Анонимным классом же можно расширить любой расширяемый класс или реализовать интерфейс с любым количеством абстрактных методов.

Анонимный класс создает новый скоуп, лямбда работает в текущем. Это значит, что объявление переменной с именем, которое уже используется снаружи, в лямбде вызовет ошибку компиляции «variable is already defined», в анонимном классе скроет (shadowing) внешнюю переменную.

С точки зрения реализации JVM, для лямбды не создается дополнительного .class файла, как это происходит для анонимного класса. Соответственно, не происходит и обычной загрузки и верификации класса. Вместо этого используется механизм invokedynamic и класс генерируется на лету с помощью LambdaMetafactory. Так что лямбда-выражения обычно работают быстрее.


Java Guru🤓 #java
🔥124👍4🌭1
Как объявить переменное количество аргументов метода?

Для этого используется аргумент-массив. В нем может находиться любое количество элементов. Еще с Java 5 для этого случая добавился синтаксический сахар: Variable-length argument (vararg). Три точки ... ставятся между типом и именем переменной, и становится можно передать любое количество аргументов, не упаковывая их в массив.

На уровне байткода применение массива и варарга не отличаются: vararg-параметр Foo... превращается в параметр-массив Foo[], на этапе вызова подставляется неявное инстанцирование и заполнение массива.

Чтобы избежать неоднозначностей, на vararg наложено ограничение: им может быть только один последний аргумент.

Vararg, как массив, может быть пустым. Иногда это приводит к неочевидному поведению. Допустим, имеем две перегрузки метода с аргументами int... и float.... Вызов такого метода без параметров попадает в вариант с int, как с более специфичным типом. Наличие же перегрузки с несовместимыми типами, например int... и boolean..., приводит при вызове к ошибке компиляции «Ambiguous method call».

Когда типом варарга используется generic-параметр, возникает warning «Possible heap pollution from parameterized vararg type». Вам нужно убедиться, что вы понимаете в чем этот риск, что ваш код не приводит к heap pollution, и уведомить об этом компилятор аннотацией
@SafeVarargs.

Java Guru🤓 #java
👍103🔥2
Что будет при вызове /api/customers/{5}, если записи c id 5 нет
👍6🔥3
🔥6👍51
This media is not supported in your browser
VIEW IN TELEGRAM
Технологии, железо и роботы на Yandex Robotics Day уже 16 августа!

На складах Маркета, Леманы Про, Перекрестка, Лавки и других компаний работают роботы Яндекса, которые помогают быстро сканировать товары, собирать посылки и перемещать заказы. Чтобы все функционировало быстро и точно, специалисты Яндекс Роботикс постоянно улучшают их.

16 августа в Москве пройдет митап, на котором они расскажут, как именно это делают:
— Серёжа Стариков выступит с докладом про коммуникационную платформу Yandex Robotics и ее применение в Yandex RMS
— Дима Мовчан объяснит, как команда создает умную роборуку с помощью imitation learning и RL
— Максим Пшибло расскажет, как с помощью Yandex Robotics Management System управлять несколькими роботами и какие алгоритмы необходимы этой системе

Кроме докладов в программе презентация нового робота, выставка тех, которые уже вовсю работают на складах, нетворкинг и неформальное афтепати с экспертами Яндекс Роботикс.

Регистрируйтесь и зовите коллег!

Реклама. ООО "ЯНДЕКС МАРКЕТ". ИНН 9704254424.
5👍1