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

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

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

Мы на бирже: telega.in/channels/javatasks/card?r=lcDuijdm
Download Telegram
Что выведет следующий код?
👍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
Как работает вывод типов?

Для
начала разберемся, что такое вывод типов. Type inference – это способность компилятора догадаться, какой тип нужно подставить, и сделать это за вас. На обычном интервью никто не спросит детали алгоритма вывода типов, достаточно будет сказать, что вывод происходит статически, только на основании типов аргументов и ожидаемого типа результата. По сути, вопрос заключается не в «как работает?», а «что это и когда возникает?».

Первое, что многим приходит в голову при фразе «вывод типов» – diamond operator <>. Он появился в Java с версии 7. Его применяют к конструкторам дженерик классов, чтобы отличать требование автоматического вывода типа от raw type.

С Java 9 diamond operator заработал и для анонимных классов.

Для дженерик методов можно указывать параметр явно, но diamond синтаксически недопустим – вывод и так сработает по умолчанию.

В Java 10 для вывода типа локальной переменной добавлено ключевое слово var. Работает это так же, как в большинстве современных языков – ключевое слово ставится вместо типа при объявлении.

Типы выводимых параметров лямбда-выражения также можно не указывать. С Java 11 вместо типа указывается ключевое слово var. Такой синтаксис дает возможность добавлять параметру модификаторы и аннотации.
👍11🔥42❤‍🔥1
Как инстанцировать экземпляр generic типа?

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

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

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

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

Когда: 29 февраля в 19:00 по мск.

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

На практике познакомимся с синтаксисом языка и напишем программу, которую часто дают новичкам на техническом интервью.

🎁 Всем, кто зарегистрировался — Гайд «Как заговорить на сленге IT-специалистов», а каждому участнику — Карта компетенций Java-разработчика. 

Погрузитесь в основы Java и задайте вопросы опытному разработчику!
👍3
Что означает ArrayStoreException?

Это исключение значит, что программа попыталась сохранить в массив значение неправильного типа. Такая попытка становится возможно из-за ковариантности массивов.

Ковариантность позволяет работать с массивом по типу массива родителей. Например, через приведение к Object[] можно попытаться положить любой объект в любой массив:

 Object x[] = new String[3];
x[0] = new Integer(0);

Компилятор гарантирует, что когда вы берете элемент из массива, он будет представителем типа элементов самого этого массива. Не важно какого типа переменная его хранит. Именно для обеспечения этой гарантии работает проверка типа времени выполнения, которая и выбрасывает ArrayStoreException.

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

// Ошибка компиляции – дженерики инвариантны!
List<Object> x = new ArrayList<String>();
👍131
Можно ли выбрасывать исключение generic-типа?

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

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

class MyClass<T extends IOException> {
void foo() throws T {
// ...
}
}
👍13🔥4
Начинаем рабочую неделю с подборки бесплатных обучающих вебинаров от «Умного города»!

27 февраля в 20:00 – Онлайн мастер-класс "Создание веб-дизайна баннера для сайта"
Аудитория: взрослые 18-35 лет
Ссылка на регистрацию: https://nordic-it-school.timepad.ru/event/2757299/

27 февраля в 17:00 – Онлайн мастер-класс для детей от 8 лет «Создание программы – переводчик в Scratch».
Ссылка на регистрацию: https://www.programmistik.ru/events/translator_scratch

28 февраля в 20:00 – Онлайн мастер-класс "Создание приложения по изучению английского языка на языке Kotlin для телефонов Android"
Аудитория: взрослые 18-35 лет
Ссылка на регистрацию: https://nordic-it-school.timepad.ru/event/2761604/

29 февраля в 17:00 – Онлайн мастер-класс для детей от 12 лет «Создаем онлайн-фотоальбом в конструкторе сайтов Tilda».
Ссылка на регистрацию: https://www.programmistik.ru/events/site_foto

Мастер-классы проводятся в трансляциях сообщества павильона «Умный город». Выбирайте и регистрируйтесь.

АНО «Цифровая трансформация» ИНН: 9709063543 Еrid:2VtzqxhnLA6
6👍2