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

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

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

Мы на бирже: telega.in/channels/javatasks/card?r=lcDuijdm
Download Telegram
🔥Путь в Java-разработке с нуля и до Middle за 15 месяцев

Уже 29 декабря стартует новая группа специализации «Java Developer» в OTUS.

💪 С нуля до Middle за 15 месяцев!

На онлайн-курсе вы получите:
✔️ Уникальные знания от преподавателей — Senior Java-разработчиков ведущих IT-компаний.
✔️ Практику создания реальных проектов — разработка своего серверного приложения на Java
✔️ Актуальные навыки, необходимые для трудоустройства Middle Java-разработчиком
✔️ Вы освоите инструменты: IntelliJ IDEA, Java Development Kit (JDK), Spring Framework, Hibernate, PostgreSQL, Apache Maven, Gradle, Docker, Kubernetes, Apache Kafka, RabbitMQ, JUnit, Postman, Jira.

👉 Получить специальные условия на курс можно оставив заявку по ссылке: https://otus.pw/tIFm/

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576, www.otus.ru
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5🥱2🔥1🐳1
Какой результат выведет следующая программа?
👍16
Какой результат выведет следующая программа?
Anonymous Quiz
4%
10
30%
15
4%
20
62%
Ошибку компиляции
👍23🎉21👏1
erid: LjN8KPXjz

👋Уважаемая публика, не проходите мимо! Только у нас на вебинаре вы узнаете то, чего ещё никогда не знали!

🔥Проникнитесь невероятными лайфхаками в жанре team lead survival на бесплатном уроке «Agile Circus: как выжить в цирке гибкой разработки ПО»: регистрация
 
На занятии обсудим:
— зачем вообще нужны гибкие подходы к организации процессов разработки (и поддержки) ПО и можно ли обойтись без них.
— как правильно выбирать способ организации разработки программного обеспечения.
— что делать в ситуации, когда одна команда не справляется.

Вебинар будет полезен тимлидам, руководителям разработки, проектным и продуктовым менеджерам, которые недовольны текущими процессами в своей компании.

👉Понравился урок — берите полный курс «Team Lead разработки», его можно пройти по скидке Чёрной пятницы, и даже в рассрочку.

Реклама. ООО "ОТУС ОНЛАЙН-ОБРАЗОВАНИЕ". ИНН 9705100963.
👍7🔥3🤣2👏1
В чём отличия интерфейса от абстрактного класса?

Главное отличие – это семантика. Интерфейсы появились еще до Java, как важная концепция ООП. Смысл интерфейса – некое поведение, описание свойства. Причем если придерживаться принципа сегрегации интерфейсов, это описание единственного аспекта поведения.

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

Отсюда вытекает естественность и необходимость множественного наследования для интерфейсов. Опыт таких языков как C++ показал, что множественное наследование классов не нужно и проблемно (см. проблема ромбовидного наследования). По факту же обычно нужно всего лишь переиспользование кода, что не относится к ООП и реализуется в некоторых языках «интерфейсами с независимым состоянием» – примесями.
В Java интерфейс в отличие от абстрактного класса не может иметь состояния. Реализация поведения же допустима только в двух случаях: для статических методов, и default для обычных. Статические методы являются частью всего класса, а не экземпляров. Дефолтная реализация, как говорилось ранее, добавлена только как хак для сохранения совместимости.

В интерфейсах, как публичных описаниях, не имеют смысла и запрещены непубличные члены. Отсюда синтаксическое отличие: модификатор public, как и abstract для методов или static для полей, можно не писать. Запрещены и модификаторы, несовместимые с abstract: final, synchronized и прочие.

На уровне скомпилированного байткода тоже есть небольшие различия: интерфейс помечается флагом ACC_INTERFACE а для класса генерируется конструктор по-умолчанию.

И есть еще одно небольшое отличие. Интерфейс с одним методом можно использовать как функциональный, и инстанциировать лямбда-выражением. Для абстрактного класса даже с единственным методом такое не сработает.
👍18🔥4
Как разработчику повысить свою ценность в команде?

Расскажем на бесплатном открытом уроке «Механизм implicits в Scala» от OTUS и Алексея Воронца – руководителя разработки в NAUMEN.

На вебинаре:

— Познакомимся с историей возникновения и мотивацией компонентов механизма.
— Разберем возможности и опасности implicit-преобразований.
— Узнаем, как и для чего служат implicit-параметры.
— Рассмотрим правила и требования, по которым Scala ищет подходящего implicit-кандидата.

Занятие пройдёт 30 ноября в 20:00 мск и будет приурочено к старту курса «Scala-разработчик». После урока вы сможете продолжить обучение на специальных условиях.

👉 Для бесплатного участия и получения записи регистрируйтесь прямо сейчас: https://otus.pw/DT0Z/

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576, www.otus.ru
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🔥2
Что если оба реализуемых интерфейса объявляют один и тот же метод?

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

Когда у обоих интерфейсов объявлены методы с одинаковой сигнатурой, но разными возвращаемыми типами – всё зависит от того, какие именно эти типы.

Переопределение метода (override) еще с Java 5 ковариантно относительно возвращаемого типа. То есть, в наследнике тип результата метода может быть наследником: super метод возвращает Number,
@Override метод возвращает Integer.

Если типы не связаны отношением наследования, например String и Long – такой класс невозможно реализовать.

Для примитивов никакой ковариантности возвращаемого типа нет. Даже если типы совместимы относительно присваивания: int→long, int→Integer. В любом из таких случаев будет ошибка о несовместимости возвращаемых типов, для примитивов они должны совпадать в точности.

Если различие в части throws, методы объявлены выбрасывающими разные типы исключений. Правила здесь те же, что для возвращаемых типов – работает ковариантность. Отличие лишь в том, что исключений примитивных типов не бывает, а даже для не являющихся родителем и наследником исключений всегда есть вариант, удовлетворяющий обоим – отсутствие выбрасываемых исключений вообще.
👍16🔥3
🤔 С чего начать обучение на Java-разработчика?

💡 С бесплатного открытого урока «HashMap под капотом» от OTUS и Михаила Ронжина – старшего Kotlin/Java developer в Tinkoff.

HashMapэто структура данных, представляет собой хэш-таблицу.

На вебинаре мы:
- познакомимся с коллекцией HashMap;
- рассмотрим основные методы;
- узнаем, как она ведет себя под капотом.

📢📢 Занятие пройдёт 5 декабря в 20:00 мск и будет приурочено к старту курса «Специализация Java-разработчик». На нем вы сможете освоить профессию с нуля до уверенного Middle.

👉 Для бесплатного участия и получения записи урока регистрируйтесь прямо сейчас: https://otus.pw/BLmN/

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576, www.otus.ru
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5🔥31🥴1
Как изменить значение приватного финального поля?

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

Для этого трюка необходимо прибегнуть к использованию Reflection API.

Сначала получим дескриптор поля – экземпляр класса Field. У объекта метакласса Class<X> интересующего нас класса вызовем метод getDeclaredField(). Просто getField() не сработает, потому что он работает только с публичными полями. Параметром передается строка с именем поля.

Полученного экземпляра Field уже достаточно для доступа к изменяемым приватным полям. Перед обращением требуется сделать его доступным, вызвав setAccessible(true).

Сам доступ осуществляется методами get*() и set*(). Так как Field представляет дескриптор поля класса, без привязки к конкретному экземпляру класса, экземпляр передается параметром в методы доступа. Для статического поля передается null.

Чтобы побороть неизменяемость финального поля, нужно снять его модификатор final. Все модификаторы поля хранятся в поле modifiers дескриптора. То есть, нужно также с помощью рефлекшена сделать доступным и обновить поле уже объекта Field.

Поле modifiers хранит модификаторы в виде битовой маски. Для изменения придется прибегнуть к битовым операторам.

Полный код установки значения 42 в поле myField объекта myObject выглядит так:

Field field = myObject.class.getDeclaredField( "myField" );
field.setAccessible( true );
Field modifiersField = Field.class.getDeclaredField( "modifiers" );
modifiersField.setAccessible( true );
modifiersField.setInt( field, field.getModifiers() & ~Modifier.FINAL );
field.setInt(myObject, 42);
👍17🔥3🥰1🎉1
Как Android-разработчику повысить квалификацию?

Прийти на практический бесплатный урок «Делаем простейшую имплементацию SDUI» от OTUS и Абакара Магомедова – Android-разработчика в «Альфа-банк».

👩‍💻На вебинаре разберем:

- в чем заключается Server Drvien UI подход;
- его плюсы и минусы;
- что нужно, чтобы реализовать простейшую его реализацию.

Занятие пройдёт 30 ноября в 20:00 мск и будет приурочено к старту курса «Android Developer. Professional». Это отличная возможность совершенно бесплатно протестировать формат обучения и задать преподавателю любые вопросы в режиме реального времени. После урока вы сможете стать студентом курса в рассрочку.

✍️ Для бесплатного участия и получения записи пройдите короткое тестирование прямо сейчас: https://otus.pw/fbLY/

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576, www.otus.ru
👍6🔥2
Как работают стримы?

Пакет java.util.stream – это средства потоковой обработки данных в функциональном стиле. Они не имеют ничего общего (кроме названия) с потоками ввода-вывода. Типичные применения – конвертация, переупаковка, и агрегация данных.

Три основных понятия Java Stream API – источник данных, промежуточная (intermediate), и терминальная (terminal) операции.

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

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

Терминальная операция «потребляет» поток. Она может быть только одна, в конце работы с отдельно взятым стримом. Стримы работают лениво – вся цепочка промежуточных операций не начнет выполняться до вызова терминальной.

Типичный пример использования стримов – map-reduce. Map – промежуточная операция, reduce – терминальная.

Источники и промежуточные операции могут изменять набор характеристик потока, которые влияют на дальнейшую обработку. Операция может иметь свойства – элементы перечисления StreamOpFlag:
• SORTED – можно сравнивать элементы;
• ORDERED – определен порядок обхода;
• DISTINCT – содержит уникальные элементы, без дублей;
• SIZED – имеет определенный размер;
• SHORT_CIRCUIT – операция, которая может приводить к короткому замыканию.
👍15🔥2
⚡️ Путь сильнейших джавистов ждет тебя!

Пройди тест по Java - проверь, готов ли ты

👩‍💻 Сможешь сдать — пройдёшь на продвинутый курс "Java Developer. Professional" от OTUS по специальной цене.

За 6 месяцев обучения:
- Научишься создавать современные java-приложения
- Поймешь основы функционирования JVM (сборка мусора, byteCode)
- Освоишь приемы применения многопоточности
- Напишешь выпускной проект на любую тему под наставничеством преподавателя

🎫Курс можно приобрести в рассрочку

👉 Пройти тест: https://otus.pw/6wJ0/

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

Самые часто используемые
👍29🔥15
This media is not supported in your browser
VIEW IN TELEGRAM
Работа мечты — это не только про карьерные возможности, но и про команду, с которой вы на одной волне. Повезло ли вам встретить таких коллег или пока только сложили образ идеального коллектива?

Расскажите о нём нейросети Kandinsky 2.2, и она создаст портрет сокомандника, с которым точно сработаетесь. Кстати, возможно, он уже ждёт вас в Сбере — вместе с крутыми проектами и насыщенной корпоративной жизнью.
6👍3🔥2🤣2🥴1
Как реализовать собственный стрим?

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

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

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

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

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

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

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

Если всё же требуется использовать отдельный пул потоков, сам стрим выполняется как задача этого отдельного пула.
👍12🔥2🎉1
👩‍💻Что должен знать востребованный Scala-разработчик?

Расскажем на бесплатном практическом уроке «Type classes в Scala» от OTUS и Алексея Воронца – руководителя разработки в NAUMEN.

На вебинаре:
— разберем type class паттерн в Scala;
— познакомимся с мотивацией его возникновения и задачами, которые он должен решать;
— сформулируем и разберем основные компоненты;
— решим ряд задач с использованием type class паттерна для закрепления на практике.

Занятие пройдёт 14 декабря в 20:00 мск и будет приурочено к старту курса «Scala-разработчик». После урока вы сможете продолжить обучение на специальных условиях.

👉 Для бесплатного участия и получения записи регистрируйтесь прямо сейчас: регистрация

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

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

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

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

Но существует один хак, способный справиться со стиранием типов. Тип-параметр все-таки остается в одном месте в рантайме. Метод метакласса наследника определившего конкретный тип getGenericSuperclass() возвращает класс, которым параметризован родитель.
🔥17👍8👏1
⚡️ Профессия Java-разработчик с нуля и до востребованного специалиста!

Уже 29 декабря стартует новая группа специализации «Java Developer» в OTUS.

👩‍💻 С нуля до Middle за 15 месяцев!

На онлайн-курсе вы получите:
➡️ Уникальные знания от преподавателей — Senior Java-разработчиков ведущих IT-компаний.
➡️ Практику создания реальных проектов — разработка своего серверного приложения на Java
➡️ Актуальные навыки, необходимые для трудоустройства Middle Java-разработчиком
➡️ Вы освоите инструменты: IntelliJ IDEA, Java Development Kit (JDK), Spring Framework, Hibernate, PostgreSQL, Apache Maven, Gradle, Docker, Kubernetes, Apache Kafka, RabbitMQ, JUnit, Postman, Jira.

👉 Получить специальные условия на курс можно оставив заявку по ссылке: https://otus.pw/YdFI/

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

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

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

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

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

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