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

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

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

Мы на бирже: telega.in/channels/javatasks/card?r=lcDuijdm
Download Telegram
Для чего используются аннотации?

Удобно рассмотреть случаи применения аннотаций с точки зрения возможных значений их свойства RetentionPolicy:

SOURCE – аннотация присутствует только в исходном коде, но не вовлечена в компиляцию. Можно разделить их на две категории:

Первая – аннотации для программиста, а не для программы. Это всевозможные маркеры. Они добавляют аннотируемым элементам некоторую специальную семантику. Более формализованный вариант документации. Примеры –
@Immutable и @ThreadSafe из Hibernate.

Вторая категория – инструкции для инструментов разработки. Примеры этой категории,
@SuppressWarnings и @Override могут влиять на предупреждения и ошибки компиляции. IntelliJ IDEA умеет понимать @Nullable и @NonNull из Spring Framework, и предупреждать о возможных NullPointerException.

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

RUNTIME – самое ходовое значение. Цель снабжается метаинформацией, доступной во время выполнения программы. Сама по себе аннотация всё так же не добавляет нового поведения. Для практической пользы runtime-аннотации в программе должен быть исполнен некоторый код процессинга, который прочитает метаинформацию инструментами Reflection API. Такой механизм широко используется во множестве популярных фреймворков: Spring, Hibernate, Jackson.
👍13🔥32🎉2
Можно ли наследовать аннотацию?

Можно понять этот вопрос по-разному. Если имеется в виду, передается ли аннотация класса-родителя классу-наследнику, ответ – по умолчанию нет. Но наследование можно включить, если на объявлении аннотации поставить мета-аннотацию @Inherited. Это работает только для классов, переопределенные методы нужно аннотировать заново.

Другой возможный смысл вопроса – наследование самих типов-аннотаций. Аннотация, как класс или интерфейс представляется в системе ссылочным типом, она тоже компилируется в .class-файл. Вы можете создать переменную с типом, скажем, java.lang.Override.

Но в отличие от других ссылочных типов, объявление аннотации (
@interface) не может иметь секций extends или implements. Это ограничение добавлено просто чтобы не усложнять систему типов. В скомпилированном коде все типы-аннотации – это интерфейсы, унаследованные от Annotation.
👍135🔥4👏1
♨️ Готовимся к собеседованию на Java разработчика Junior+/ Middle: проверьте свои знания

На данном мероприятии мы подробно разберем, какие вопросы могут возникнуть на собеседовании на позицию Java Middle Developer.
Урок будет полезен каждому, кто желает оценить свой уровень понимания Java.

В результате посещения вебинара:
- Вы сможете уверенно ответить на большинство вопросов, которые могут возникнуть на интервью для уровня Java Middle Developer;
- будете осведомлены о подводных камнях, связанных с ответами на эти вопросы.

После открытого урока вы сможете записаться на курс для продвинутых разработчиков «Java Developer. Professional» по специальной цене.

Событие пройдет 20 февраля в 20:00 МСК
Участие бесплатное

➡️ Зарегистрироваться!

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

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

Начиная с Java 8 в стандартную библиотеку добавлена мета-аннотация
@Repeatable.
Механизм ее действия такой же, как раньше: помечая ей интересующую аннотацию, необходимо указать параметром
@Repeatable аннотацию-контейнер. Нововведение заключается в синтаксисе использования: теперь набор аннотаций оборачивается в контейнер неявно.

Со стороны Reflection при чтении мета-информации тоже появилась возможность не оперировать контейнером явно – метод getAnnotationsByType при необходимости найдет и развернет этот контейнер.
9👍6🔥2
Начал изучать Java?☕️

Приходи на бесплатный урок «Основы объектно-ориентированного программирования в Java» от OTUS.

На вебинаре обсудим основы ООП, лежащего в основе языка Java, посмотрим как его использовать при написании кода, и какие преимущества он предоставляет.

Урок будет полезен тем, кто хочет:
— Начать изучать Java с нуля.
— Не знает с какой стороны подойти к теме ООП (не только в языке Java).

Занятие пройдёт 22 февраля в 20:00 мск и будет приурочено к старту курса «Java-разработчик». Программа обновлена и полностью отвечает современным требованиям рынка.

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

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🔥3
Что выведет следующий код?
👍63🔥2👏1
💗 Новый проект оказался сложнее, чем вы ожидали. Всё равно попробуете с ним справиться, спросите совета у ChatGPT или отдадите более опытному коллеге?

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

В конце теста вас ждёт скидка 14% на карьерную консультацию с 12 по 19 февраля. Не забудьте забрать.

Реклама. ООО «Хэдхантер»‎, 129085, г. Москва, ул. Годовикова, д.9, стр.10, ОГРН 1067761906805. erid: 2VtzqwZ7CLR
Подробнее об условиях акции.
👍4🔥2
Как используется @⁠Deprecated?

Этой аннотацией помечают код, который устарел и не должен быть более использован. Классы, которые используют или переопределяют @Deprecated элементы, будут компилироваться с warning-ом.

Имеет retention RUNTIME, что значит, что фреймворки могут динамически проверять наличие аннотации на элементе с помощью Reflection API.

Начиная с Java 9 у этой аннотации появились опциональные параметры – строка since и булево значение forRemoval. В since указывается версия вашего приложения, начиная с которой элемент считается устаревшим. Значение true в forRemoval предупреждает, что со следующей мажорной версии этот элемент будет удален. Такое нововведение связано с изменением политики устаревания – с Java 9 и устаревшие элементы самой JDK тоже могут удаляться в будущих версиях.

Обычно, когда элемент помечают устаревшим, причины устаревания и дальнейшие рекомендации указывают в его Javadoc-документации под тегом
@deprecated.
👍15🔥41
This media is not supported in your browser
VIEW IN TELEGRAM
Приглашаем на Infra Meetup #3 — митап про надежность от Яндекс Такси и Техплатформы Екома и Райдтеха

На митапе поделимся тремя докладами об инструментах надежности в Такси, платформе биллинга Екома и Райдтеха и возможностях фреймворка userver для поддержания отказоустойчивости. В конце митапа участников ждет нетворкинг и экскурсия по питерскому офису.

Формат: офлайн или онлайн
Место встречи: Санкт-Петербург, БЦ «Бенуа»
Дата и время: 29 февраля, 18:00

Бесплатно. Количество офлайн мест ограничено. Регистрация обязательна

Подробнее

Реклама. ООО "Яндекс.Такси", ИНН: 7704340310
👍7🔥2🥴1
Что такое Type Erasure?

Компилятор удаляет из байткода класс-файла информацию о типах-дженериках. Этот процесс и называется стирание типов (type erasure). Он появился в Java 5 вместе с самими дженериками. Такое решение позволило сохранить обратную совместимость без перекомпилляции кода Java 4.

Стирание состоит из трех действий:
🔘 Если параметры ограничены (bounded), вместо типа-параметра в местах использования подставляется верхняя граница, иначе Object;
🔘 В местах присвоения значения типа-параметра в переменную обычного типа добавляется каст к этому типу;
🔘 Генерируются bridge-методы.

Информация о типах стирается только из методов и полей, но остается в метаинформации самого класса. Получить эту информацию в рантайме можно с помощью рефлекшна, методом Field#getGenericType.

Тип со стертой информацией о дженериках называется «Non-reifiable».

Стирание типов позволяет не создавать при применении дженериков новые классы, в отличие от, например, шаблонов C++.
👍18🔥2
👩‍💻 Пройди тест по Java и проверь свои знания.

Ответишь
— пройдешь на продвинутый курс "Java Developer. Professional" от OTUS по специальной цене + получишь доступ к записям открытых уроков курса курса

🔝 Обновленная, расширенная программа

Группа стартует 29 февраля - успей присоединится на выгодных условиях.

👉 ПРОЙТИ ТЕСТ: https://otus.pw/TQgg/

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

В объявлении дженерик-параметра класса или метода может быть указана его верхняя граница (bound)

class Foo<T extends Number>

Ключевое слово extends применяется как для классов, так и для интерфейсов. Фактическим параметром такого класса Foo может быть или сам Number, или его наследники.

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

Тип-параметр может иметь несколько верхних границ, то есть границу-пересечение типов: <T extends Comparable & Serializable>. Стирание произойдет до первой из границ, остальные послужат только ограничением вариантов фактического типа. Поэтому граница-класс, при наличии, должна быть указана раньше границ-интерфейсов.
При указании значения дженерик-параметра переменной может быть использован вайлдкард – символ ?. Вайлдкард значит, что мы не собираемся использовать информацию о конкретном типе, этот тип может быть любым. Это не то же самое, что не указать дженерик параметр совсем.

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

Кроме того в случае вайлдкарда можно задать нижнюю границу

Foo<? super Number> foo;

Означает, что мы не будем использовать информацию о конкретном типе, но будем знать что это предок класса Number. То есть или сам Number, или Object.

В объявлении класса или метода использование super запрещено, так как не имеет смысла.

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

Хороший API должен уметь эффективно работать с классами-наследниками, то есть быть ко- или контравариантным где это необходимо. При этом без bounded вайлдкардов не обойтись. Чтобы запомнить, какая граница нужна в каких случаях, Joshua Bloch предложил мнемонику PECS:
Producer-extends, Consumer-super
👍113🔥2
Присоединяйтесь к нашему бесплатному курсу и начните увлекательное путешествие в мир Java!

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

🎓 Чему вы научитесь:
— Создавать программы с использованием основных конструкций языка.
 — Разделять код на методы для повторного использования.
 — Анализировать ошибки в коде с использованием отладочной печати.

💼 Включено в курс:
29 уроков (видео и/или текст), 35 упражнений в тренажере, 95 проверочных тестов + дополнительные материалы.

Вы с нами?😉
8🔥4
Что такое ковариантность и контравариантность?

Формально, ковариантность/контравариантность типов – это сохранение/обращение порядка наследования для производных типов. Проще говоря, когда у ковариантных сущностей типами-параметрами являются родитель и наследник, они сами становятся как бы родителем и наследником. Контравариантные наоборот, становятся наследником и родителем.

Легче всего осознать эти понятия на примерах:
🔘 Ковариантность: List<Integer> можно присвоить в переменную типа List<? extends Number> (как будто он наследник List<Number>).
🔘 Контравариантность: в качестве параметра метода List<Number>
#sort типа Comparator<? super Number> может быть передан Comparator<Object> (как будто он родитель Comparator<Number>)

Отношение типов «можно присвоить» – не совсем наследование, такие типы называются совместимыми (отношение «is a»).

Существует еще одно связанное понятие – инвариантность. Инвариантность – это отсутствие свойств ковариантности и контрвариантности. Дженерики без вайлдкардов инвариантны: List<Number> нельзя положить ни в переменную типа List<Double>, ни в List<Object>.

Массивы ковариантны: в переменную Object[] можно присвоить значение типа String[].

Переопределение методов начиная с Java 5 ковариантно относительно типа результата и типов исключений.
👍16🤔3🎉31🔥1
Девять шаблонов проектирования ПО, которые вы должны знать!

Освойте их на бесплатном практическом уроке от OTUS и Андрея Полякова — старшего разработчика в Unlimint.

После вебинара вы сможете:
– понимать основные принципы и концепции, лежащие в основе шаблонов GRASP;
– оценивать и выбирать наиболее подходящие шаблоны для конкретных проектов;
– разрабатывать архитектуры, основанные на принципах GRASP, что позволит создавать более качественное и надежное ПО.

Занятие пройдёт 29 февраля в 20:00 мск в рамках курса «Архитектура и шаблоны проектирования». Доступна рассрочка на обучение!

➡️ Пройдите короткий тест прямо сейчас, чтобы посетить бесплатный урок и познакомиться с форматом обучения: пройти тест

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

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

Проблема решается простым и безопасным кастом. Компилятор генерирует новый метод, который совпадает по сигнатуре с родительским. В его теле параметр кастуется и вызов делегируется в пользовательский метод. Это и называется bridge методом.

Bridge method можно увидеть с помощью рефлекшна. Его имя совпадает с оригинальным методом, но параметр имеет тип, в который сотрется дженерик родителя. Этот метод будет помечен флагом synthetic, что значит, что он написан не программистом а компилятором.

Попытка написать такой же метод вручную приведет к ошибке компиляции.
👍21🔥4👏2❤‍🔥11
⁉️ Как стать разработчиком на Spring в 2024?

Узнайте на бесплатном практическом уроке от OTUS, где опытный эксперт приоткроет закулисье нашего курса и расскажет:

✔️ как грамотно выбрать итоговый проект, чтобы использовать его для портфолио и получить максимум практических навыков;
✔️ какие требования мы предъявляем к проектам студентов;
✔️ как проходит реализация проектов.

📢📢 Занятие пройдёт 28 февраля в 20:00 мск и будет приурочено к старту курса «Разработчик на Spring Framework».
Доступна рассрочка на обучение!

➡️ Пройдите короткий тест прямо сейчас, чтобы занять место на открытом уроке и получить запись: https://otus.pw/VSkT/

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

Как было сказано ранее, массивы в Java ковариантны. А значит, можно обратиться к объекту типа String[] через переменную типа Object[], и положить туда например Integer. Такой код скомпилируется, но в момент записи произойдет ArrayStoreException.

Дженерики защищены инвариантностью. Если попытаться положить List<Object> в List<String>, эта же по сути ошибка произойдет уже на этапе компиляции.

Heap pollution – ситуация, когда эта защита не срабатывает, и переменная параметризованного типа хранит в себе объект, параметризованный другим типом. Простейший пример:

List<String> strings = (List) new ArrayList<Integer>();

Документация гарантирует, что при компиляции всего кода целиком, heap pollution не может возникнуть без варнинга этапа компиляции.
Heap pollution может произойти в двух случаях: при использовании массивов дженериков и при смешивании параметризованных и raw-типов.

Raw types – это параметризованные типы без указания параметра. Пример с raw types, приводящий к heap pollution, уже был описан выше:

List<String> strings = (List) new ArrayList<Integer>();

Использовать raw types не надо вообще, причины подробно изложены в главе 26 Effective Java. Если информация о дженериках не нужна, используется символ wildcard (<?>).

Компилятор не даст создать массив параметризованного типа, это приведет к ошибке generic array creation. Картинка выше иллюстрирует, к чему это могло бы привести.

Параметризованный тип varargs-аргумента метода вызывает ту же проблему, т.к. varargs – не что иное как параметр-массив. Вот почему он так же приводит к предупреждению компилятора «possible heap pollution». Если вы уверены что риска нет, с Java 7 это предупреждение заглушается аннотацией
@SafeVarargs.
👍12🔥32🥰1
💪 Как Java-разработчику повысить квалификацию и увеличить доход в 2024?

Освоить JVM с профилированием и оптимизацией приложений в облаках на онлайн-курсе «Java Developer. Advanced» от OTUS.

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

На курсе вас ждут:

▫️ живые вебинары с возможностью задать вопросы экспертам;
▫️много практики и сильные проекты для портфолио;
▫️поддержка профессионального комьюнити;
▫️ рассрочка на комфортных условиях.

🤝 Проверьте свои навыки пройдя тест и получите специальную цену: https://otus.pw/LiVg/

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