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

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

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

Мы на бирже: telega.in/channels/javatasks/card?r=lcDuijdm
Download Telegram
При вызове метода executeTask() три раза, сколько экземпляров TaskProcessor будет создано?
Anonymous Quiz
51%
Один, так как TaskManager синглтон
2%
Два, просто на удачу
41%
Три, так как TaskProcessor prototype
3%
Ошибка компиляции
2%
RuntimeException
👍11🔥51🥴1
🔍23 апреля(уже завтра!) в 19:00 по мск приходи онлайн на открытое собеседование, чтобы посмотреть на настоящее интервью на Middle Java-разработчика.

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

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

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

Реклама. ООО "ШОРТКАТ", ИНН: 9731139396, erid: 2Vtzquwsnpa
Please open Telegram to view this post
VIEW IN TELEGRAM
3👍2🔥2
Что произойдёт при запуске Spring-приложения с таким классом?
👍4🔥3
Что произойдёт при запуске Spring-приложения с таким классом?
Anonymous Quiz
22%
Не запустится, так как нельзя использовать обе эти аннотации на одном классе
9%
Запустится, но Spring не создаст ни одного бина из-за конфликта
55%
Запустится, будет зарегистрирован один бин
6%
Запустится, но будет RuntimeException
👍16🔥5
👩‍💻 Разработка на Java требует глубокого понимания не только языка, но и принципов работы JVM, многопоточности и современных фреймворков.

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

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

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

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

🎁 Начните обучение со скидкой, подробности у менеджеров. ПРОМОКОД: JAVA_04

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Please open Telegram to view this post
VIEW IN TELEGRAM
👍32🔥2
Что будет результатом кода?
🔥5👍3
Что будет результатом кода?
Anonymous Quiz
34%
Ошибка компиляции
6%
RuntimeException
46%
0
13%
null
2%
number
👍7🔥7😁3
Как реализовать собственный стрим?

Любой стрим определяется его сплитератором. Spliterator – это специальный разделяемый внутренний итератор.

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

Поток создается из сплитератора одним из статических методов класса StreamSupport. Вызов его методов осуществляется самим фреймворком. Вкратце его работа выглядит так:
• Элементы перебираются методом tryAdvance, пока он не выдаст false. Через параметр action к элементу применяются последующие операции.
• При применении промежуточных и терминальных операций учитываются характеристики потока, изначально задаваемые методом characteristics.
• Когда обработка стрима распараллеливается, методом trySplit от начала последовательности элементов «откусывается» часть, и возвращается завернутой в новый сплитератор. Текущий продолжает идти по оставшемуся хвосту. В идеале, по возможности эта часть – половина элементов потока. Если разделить уже нельзя, возвращается null.


Java Guru🤓 #java
👍7🔥53
Бесплатный урок по Apache Kafka⭐️

Учим работать с реальными исходными данными, а не на теоретических примерах.

Расскажем про язык Кафки: топики, партиции, продюсеры-консьюмеры, кластер, ноды. 

Рассмотрим: как работают очереди сообщений, сколько должно быть консьюмеров для эффективной вычитки, как повысить надёжность кластера с помощью репликации данных.

Покажем, как развернуть кластер Кафки на своём ПК с 3 нодами, schema-registry и авторизацией.

Обычно в инструкциях кластер из 1 ноды, зукипера и 1 брокера, но это не наш путь, смотрим сразу на практике.

Забрать урок👉🏻 в боте
👍32🔥2
Как работают параллельные стримы?

Основная цель, ради которой в Java 8 был добавлен Stream API – удобство многопоточной обработки.

Обычный стрим будет выполняться параллельно после вызова промежуточной операции parallel(). Некоторые стримы создаются уже многопоточными, например результат вызова Collection#parallelStream(). Для распараллеливания используется единый общий ForkJoinPool.

Внутри реализации потока его сплиттератор оборачивается в AbstractTask, который и отправляется на выполнение в пул. AbstractTask при выполнении считывает estimateSize сплиттератора и текущую степень параллелизма пула. На основе этих данных он принимает решение, распараллелить ли сплиттератор на два методом trySplit().

У удобства такого решения есть обратная сторона. Так как пул единый, нагрузка распределяется на всех пользователей параллельных стримов в программе. Если в одном потоке выполняются долгие блокирующие операции, это может ударить по производительности в совершенно не связанном с ним другом потоке.

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


Java Guru🤓 #java
👍9🔥6🤯2
🤖 Хотите автоматизировать инфраструктуру для тестирования прямо в Gradle?

На открытом уроке «Облако в кармане: запускаем всю инфраструктуру для теста при сборке» от OTUS мы расскажем, как избежать ручных настроек и запусков. Вместо этого вы научитесь автоматизировать весь процесс с помощью Docker, DockerCompose и TestContainers, интегрируя их с Gradle.

Урок полезен для разработчиков на Kotlin и Java, которые работают с автотестами — интеграционными и end-to-end.

В ходе урока вы освоите:
▫️Автоматический запуск всей необходимой инфраструктуры для тестирования.
▫️Создание Docker-образов для тестов и деплоя.
▫️Разработку автотестов, которые поднимут ваши навыки на новый уровень.

Участники получат скидку на курс «Kotlin Backend Developer. Professional».

➡️ Встречаемся 29 апреля в 20:00 МСК, регистрация открыта: https://vk.cc/cL6SbA

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

Внутри класса class Foo<T> на generic параметре T невозможно выполнить никакой оператор: нельзя взять его .class, нельзя применить его в instanceof. Также и вызов на нем оператора new приведет к ошибке.

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

Стандартный простой способ действия здесь – кроме значения типа T передавать еще и объект-дескриптор для этого типа, экземпляр класса Class<T>. Объект может быть создан из дескриптора рефлекшеном.

Но существует один хак, способный справиться со стиранием типов. Тип-параметр все-таки остается в одном месте в рантайме. Метод метакласса наследника определившего конкретный тип getGenericSuperclass() возвращает класс, которым параметризован родитель.


Java Guru🤓 #java
👍20🔥74
Как написать иммутабельный класс?

Immutable (неизменяемый) класс – это класс, состояние экземпляров которого невозможно изменить после создания.

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

Шаги, которые необходимо предпринять, чтобы класс стал immutable:

1. Запретите расширение класса – либо объявите его final, либо закройте доступ наследникам ко всем способам мутации, перечисленным в следующих пунктах;
2. Сделайте все поля финальными;
3. Не выставляйте наружу методов-мутаторов, которые меняют состояние;
4. Не отдавайте наружу поля ссылочного изменяемого типа (объекты классов, массивы) – если объект под ссылкой не иммутабельный, должна возвращаться его глубокая копия (defensive copy);
5. Создавайте объект правильно (подробнее в следующем посте).

Если вам нужны преимущества иммутабельного объекта, но также нужно иногда изменять его, подойдет подход copy on write: каждый метод-мутатор должен мутировать и возвращать не сам объект, а только что созданную его копию. Оригинал всё так же остается неизменным.


Java Guru🤓 #java
👍15🔥83
Как инициализировать иммутабельный класс?

Если прочитать определение immutable-объекта внимательно, момент его создания – это единственный этап в жизненном цикле, когда объект может меняться. Действительно, как иначе установить это неизменяемое состояние. Отсюда, при неправильной реализации, вытекают некоторые риски дальнейшей неизменяемости.

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

Вторая проблема, с которой вы гораздо менее вероятно столкнетесь, но о которой нужно знать: без должной синхронизации в многопоточной среде конструктор может получить ссылку на не до конца сконструированный объект. Для поддержки создания объектов в многопоточной среде нужно обеспечить создание его полей happens-before. Проблема аналогична double-checked блокировке без ключевого слова volatile – детали можно почитать
здесь.

Что касается удобства создания immutable объектов. Если класс состоит из всего пары полей – дополнительные действия скорее всего не нужны, хватит обычного конструктора.

Однако, когда полей много, это становится проблемой. В Java, в отличие от таких языков как например TypeScript или Kotlin, нельзя указывать имена передаваемых параметров. Обычно можно воспользоваться сеттерами, но в неизменяемом классе их нет.

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

На помощь приходят порождающие паттерны. Самый распространенный подход – builder (паттерн Строитель). Для иммутабельного типа Foo создается дополнительный изменяемый класс FooBuilder. В билдере есть сеттеры для каждого поля. Эти сеттеры обычно возвращают this, что позволяет вызывать их в цепочке. Цепочка заканчивается методом build(), который уже создает иммутабельный Foo.

Каждый сеттер выполняет роль именованного параметра. Сам билдер, как обычный объект, можно передавать от компонента к компоненту, делегируя им части инициализации. Использование этого паттерна логически разделяет существование объекта типа Foo на два этапа – создание и использование.


Java Guru🤓 #java
👍11🔥53
Как реализовать метод equals?

Сначала нужно решить, действительно ли вам нужно переопределять equals(). Реализация по умолчанию делает объект равным только самому себе (сравнение на идентичность). Это имеет смысл, если у вашего класса не бывает отдельных, но логически одинаковых экземпляров.

Если два экземпляра всё-таки могут быть равны, equals() нужно переопределять. Реализация должна соблюдать контракт: это отношение эквивалентности (рефлексивность, транзитивность, симметричность), ни один объект не равен null.

Рефлексивность. первым делом проверим, не идентичен ли переданный объект текущему. Если да – сразу вернем true.

Неравенство null. Если аргумент null – сразу вернем false.

Симметричность. Если мы допускаем наследование и расширение метода equals(), в наследнике может появиться дополнительная логика, которая сделает !other.equals(this) при this.equals(other). Проще всего избежать этого, добавив сравнение типов. Если типы не равны – сразу вернем false. Почему не надо использовать instanceof.

Транзитивность. Оператор == обладает свойствами транзитивности и симметричности. Далее мы сравниваем на равенство все примитивные свойства. Для ссылочных типов этими характеристиками по контракту обладает equals – для сравнения ссылочных типов пользуемся им.

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


Java Guru🤓 #java
👍13🔥53
Хотите прокачать карьеру в разработке на Java, но не знаете, с чего начать?

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

На курсе вы:

- Научитесь разрабатывать приложения на Scala.
- Освоите популярные библиотеки и подходы функционального программирования.
- Погрузитесь в микросервисы, Akka, CQRS и другие технологии.

Пройдите короткое тестирование и получите скидку на обучение:

https://vk.cc/cLeddk
4👍2🔥2
Как реализовать метод hashCode?

Если вы переопределили equals(), то обязательно также переопределить и hashCode(). Это не просто теоретическое требование. Если класс нарушает это правило, хранение его экземпляров в качестве например ключей HashMap приводит к непредсказуемому поведению.

Результат hashCode() должен быть одинаковый для равных в смысле equals объектов. Обычно для этого значение хэш-кода вычисляется на основе значений полей, которые участвуют в equals(). Но и возвращение одной и той же константы 42 для любого экземпляра класса тоже будет валидной реализацией.

Результат hashCode() должен быть равномерно распределен. Это правило не такое строгое как остальные. Его нарушение не сломает программу, хотя может сильно ухудшить производительность. Поэтому константа 42 – допустимая, но не лучшая идея. Вместо этого все значения полей сначала приводятся к int: boolean превращается в любую пару констант, null в 0, для ссылочных типов берется их hashCode(). Затем все эти значения смешиваются с помощью бинарного оператора XOR (^). Дополнительно для лучшего распределения можно применять битовые сдвиги. Если вы владеете информацией о распределении значений полей в конкретно вашем случае, эту реализацию можно улучшить.

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


Java Guru🤓 #java
👍95🔥5
Чем отличается Closeable от AutoCloseable?

Интерфейс AutoCloseable представляет объект-хранилище некоего ресурса, пока тот не закрыт. В единственном его методе close() объявляется логика закрытия этого ресурса. Пример – дескриптор открытого файла (ObjectOutputStream).

Особенность этого интерфейса в том, что его применение позволяет использовать объект в языковой конструкции try-with-resource. Всё это появилось в Java версии 7.

До Java 7 уже существовал похожий интерфейс – Closeable. Смысл его точно такой же. Он всё еще доступен в стандартной библиотеке для обратной совместимости, но в новом коде рекомендуется использовать AutoCloseable. Чтобы экземпляры старого Closeable тоже можно было использовать в try-with-resource, новый интерфейс был добавлен его родителем.

Проблема старого интерфейса Closeable была в узости типа исключений, которые может выбрасывать close(). Ковариантность позволила расширить тип в базовом интерфейсе AutoCloseable с IOException до Exception.

Еще одно отличие – контракт метода close(). Старый Closeable требует его идемпотентности, тогда как новый AutoCloseable разрешает методу иметь побочные эффекты.


Java Guru🤓 #java
👍103🔥3
Что будет результатом кода?
👍52🔥2
Что будет результатом кода?
Anonymous Quiz
16%
Ошибка компиляции
8%
123456
64%
234567
1%
4567
11%
IllegalStateException
👍122🔥2