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

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

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

Мы на бирже: telega.in/channels/javatasks/card?r=lcDuijdm
Download Telegram
👩‍💻 Что такое Reflection API и как с этим работать?

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

Встречаемся 7 августа в 20:00 мск.

Спикер Александр Фисунов — Senior Kotlin Developer в SSP Software на проекте ВТБ, опытный Java-разработчик и кандидат технических наук.

👉 Регистрируйтесь прямо сейчас, чтобы не пропустить мероприятие: https://vk.cc/cyTeXM

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576, www.otus.ru
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥42👍2
Зачем нужен загрузчик классов?

В Java используется динамическая загрузка классов. Ее выполняют загрузчики – наследники абстрактного класса ClassLoader. Кроме того, они же загружают и файлы-ресурсы.

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

Вручную класс можно загрузить из конкретного загрузчика, передав аргументом его метода loadClass бинарное имя класса.

В URLClassLoader и стандартных загрузчиках JVM источником класса служит .class-файл. Другие загрузчики в своей реализации используют и другие источники: это может быть сетевой ресурс, или класс может генерироваться в рантайме. К примеру загрузчик из javassist специализируется на создании классов на лету.

В результате загрузки создается экземпляр класса Class. В отличие от обычных объектов, такие экземпляры хранятся не в куче, а в permgen/metaspace. Class может быть выгружен, когда загрузивший его ClassLoader стал мусором.
👍124🔥3
Тестовое собеседование на Middle Java-разработчика в эту среду

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

Как это будет:
1. Степан Аракелян, ex-Tech Lead в МТС и ментор в ШОРКТАТ, проведет настоящее собеседование на Middle Java-разработчика
2. Степан будет комментировать каждый ответ респондента, чтобы дать понять чего от вас ожидает собеседующий на интервью
3. В конце можно будет задать любой вопрос Степану

На открытом эфире ШОРТКАТ ты узнаешь:
- Чего ждут от кандидатов на Middle позиции в Java-разработке
- Какие вопросы задают на интервью и зачем
- Как подготовиться к собесу, чтобы получить оффер

Это бесплатно?
Бесплатно

Переходи в нашего бота, чтобы получить ссылку на эфир → @shortcut_sh_bot
🎉7👍4🔥2
Какие существуют стандартные загрузчики классов?

В JVM встроено как минимум три стандартных загрузчика:

🔘 Bootstrap – встроенная в JVM нативная реализация, родитель для всех остальных загрузчиков. Загружает часть стандартных классов java.*;
🔘 Platform – отвечает за загрузку стандартных классов Java-рантайма. До Java 9 назывался Extension и занимался загрузкой расширений. Гарантируется, что ему будут видны (но не факт что загружены непосредственно им) все стандартные классы Java SE и JDK;
🔘 System (Application) – загружает классы из classpath конкретного приложения;

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

Иллюстрация смысла этой иерархии – загрузчики web-сервера Apache Tomcat. Прикладной код каждого web-приложения работает на своем отдельном загрузчике изолированно от других приложений. Даже один и тот же класс-singleton у каждого приложения будет собственный. Системные классы и общие библиотеки при том грузятся их родительскими загрузчиками, только один раз для сервера.
👏11👍6
Офер в Яндекс для опытных бэкендеров за два дня

24–25 августа приглашаем бэкендеров с опытом работы от пяти лет получить офер в Яндекс через multitrack за 2 дня. Достаточно решить задачи онлайн до 20 августа и пройти несколько технических секции 24 августа, чтобы уже 25-го получить офер и выбрать три команды, к которым вам было бы интересно присоединиться.

Как правило, за несколько собеседований сложно понять, подходит ли вам команда и наоборот. Multitrack позволит вам поработать в трёх разных командах Яндекса и выбрать подходящую. Вы сможете погрузиться в рабочие процессы, познакомиться с будущими коллегами и понять, с какими задачами и технологиями хотите работать.

Узнать подробности и зарегистрироваться.

Реклама. ООО "Яндекс". ИНН 7736207543
🔥42👍2😁1
Чем отличается перегрузка от переопределения?

Полиморфизм – соль ООП. Перегрузка (overload) и переопределение (override) – два инструмента достижения полиморфного поведения в Java.

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

Ad-hoc – не совсем настоящий полиморфизм, так как при нём используется раннее, или статическое связывание (early binding, static dispatch). Это значит, что для выбора конкретного варианта метода используется информация о типе переменной, а не объекта в ней лежащего, и происходит это еще при компиляции.

Если в классе объявлены два перегруженных метода, а аргумент в вызове подходит под оба, случится ошибка компиляции. В примере выше компилятор не может выбрать между вариантами метода println с параметром char[] и со String, так как null может быть и тем и другим.

Переопределение (override) дает полиморфизм подтипов. Это реализация/подмена метода нефинального родительского класса или интерфейса. С помощью этого механизма достигается поведение, когда экземпляр хранится под типом родителя, но реализация методов используется специфичная для этого конкретного подтипа. Пример:
List<String> list = new LinkedList<>();
list.add(“foo“);


Здесь метод add вызывается общий для всех списков, но добавлен будет именно элемент связного списка.

Выбор конкретного метода происходит в последний момент, в процессе работы программы, в зависимости от типа объекта. Это называется позднее или динамическое связывание методов (late binding, dynamic dispatch).

Переопределение имеет непосредственное отношение к принципу подстановки Лисков (LSP): в хорошем объектно-ориентированном коде для вызывающего кода переопределенный метод не должен быть отличим от оригинального.

Переопределенный метод принято снабжать аннотацией
@Override. Ее отсутствие допускается, но компиляция не перегружающего метода с такой аннотацией приведет к ошибке.

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

Статические методы нельзя переопределить, можно только перегрузить.
👍13🔥122
⚡️ Узнайте, как манипулировать байт кодом Java-приложений!

На открытом уроке курса «Java Developer. Advanced» разберем, как просматривать и читать байт код классов и для чего это может быть нужно. Научитесь создавать утилиты для изменения байт кода существующих классов в runtime. Это знание поможет вам улучшить производительность ваших приложений и решать сложные задачи.

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

Встречаемся 7 августа в 20:00 мск.

Спикер — Tech Lead в одном из крупнейших российских банков и кандидат технических наук.

👉 Регистрируйтесь прямо сейчас, чтобы посетить бесплатное занятие: https://vk.cc/cz2snD

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

Singleton – это паттерн проектирования «одиночка», класс с единственным экземпляром. Такая пространная формулировка открывает простор для подходов к реализации, а значит и для уточняющих вопросов, на которые и рассчитывает интервьюер.

Первое что надо выяснить – единственный экземпляр в рамках чего. В базовом случае уникальность объекта обеспечивается на уровне реализации класса. Но при этом базовом подходе создается по объекту на каждый класслоадер. Для уникальности на всю виртуальную машину реализацию нужно дополнить. Понадобится больше действий уже на уровне ОС чтобы добиться единого экземпляра между процессами JVM. С другой стороны, может требоваться специфичное для фреймворка сужение «области уникальности», например по экземпляру на каждый Spring IoC-контейнер.

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

И наконец нужно уточнить, в каких обстоятельствах подразумевается его использовать. Обычно предлагают условие многопоточной среды – инстанцирование необходимо синхронизировать. Другое возможное требование – сохранение состояния от запуска к запуску. Спектр опций здесь ограничивается только фантазией собеседующего.
👍12🔥5
📚 Пройди тест на знание Java и получи доступ к 7️⃣2️⃣ открытым урокам по Java

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

📊 -Курс рассчитан на профессионалов с практическим опытом работы на Java.
На курсе вы освоите:
- создание современных Java-приложений;
- основы функционирования JVM (сборка мусора, byteCode);
- приемы применения многопоточности;
- решение задач уровня Middle+;
- современные фреймворки Spring WebFlux, Kafka, реактивный Postgres и Kubernetes;
- написание кода чище и быстрее.

Забудьте о скучном обучении — здесь вас ждут настоящие челленджи и нестандартные практические решения. А еще сильные проекты для портфолио и карьерный сапорт! 📅 Старт группы уже 29 августа 2024г. Доступна рассрочка на обучение.

➡️ НАЧАТЬ ТЕСТИРОВАНИЕ

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576, www.otus.ru
Please open Telegram to view this post
VIEW IN TELEGRAM
👍52🥰2🔥1
Чем отличается interface от @⁠interface?

Среди интерфейсов выделяется особая группа, которая не объявляет никаких методов. Пример такого интерфейса – Serializable. Такие интерфейсы добавляют классу некую семантику, которая позже используется либо с помощью рефлексии (и instanceof), либо вообще не программно, а как информация для разработчиков и инструментов разработки. Это маркерные интерфейсы. Маркерный интерфейс представляет метаинформацию класса.

Начиная с Java 1.5 в языке появился новый вид типов – аннотации. Они берут на себя и расширяют возможности маркерного интерфейса:
1. Можно применять аннотацию не только к классу или интерфейсу, но почти к чему угодно: к пакетам, к методам, их параметрам, переменным. Полный список представлен в перечислении ElementType;
2. Аннотация может нести данные в своих элементах
3. Аннотация может не присутствовать в рантайме, или даже остаться только в исходнике, не попав в байткод вовсе. Определяется ее RetentionPolicy;
4. Можно сделать аннотацию не наследуемой, просто не помечая ее
@Inherited;
5. И конечно же, синтаксис. Примененная аннотация с первого взгляда отличается от настоящих интерфейсов.

Joshua Block в главе 37 Effective Java выделяет два преимущества маркерных интерфейсов перед аннотациями на этапе компиляции:
1. Можно требовать использование только маркированного параметра, так как маркерный интерфейс – это еще и тип;
2. Можно сузить применяемость маркера к только определенным типам, сделав интерфейс их наследником.

Возвращаясь к вопросу, ключевое слово
@interface объявляет аннотацию, interface – интерфейс.

В результате компиляции в .class-файле аннотация превращается в интерфейс-наследник java.lang.annotation.Annotation, помеченный флагом ACC_ANNOTATION. Элементы превращаются в абстрактные методы. Этим объясняется синтаксис объявления. Специфичные для аннотаций атрибуты описаны в JVMS 4.7.16-4.7.22.

К слову, конструкции вида
@something в javadoc называются тэгами. Они выглядят похоже на аннотации, также представляют метаинформацию для документации, но технически не имеют с ними ничего общего.
👍10🔥4🎉32
Когда Class.getClassLoader вернет null?

Этот вопрос поднимает две темы. Первая – класс Class в целом. Экземпляры Class<T> представляют runtime-описание типов. В терминах этого описания перечисления считаются классами, аннотации – интерфейсами. В основном приходится взаимодействовать с метаклассами при работе с рефлексией или загрузчиками.

По большей части эти экземпляры класса Class состоят из содержимого .class-файла. Создаются они только внутри класслоадера. Особенности их хранения в памяти обсуждаются в
предыдущем посте.

Вторая тема для разговора здесь – особенности класса Class для примитивов, массивов и void. Для получения таких экземпляров используется тот же синтаксис, что и для обычных классов: void.class, int.class, float[][].class. Конструкция foo.class – это не обращение к члену, а литерал класса.

Для void типом-параметром T выступает специальный неинстанциируемый тип java.lang.Void. Тип-параметр примитива – соответствующий класс-враппер. Хотя для самого класса-враппера будет отдельный экземпляр Class. То есть int.class != Integer.class.

Метод getClassLoader обычного класса или интерфейса вернет загрузчик, который его загрузил. null может вернуться для загруженного bootstrap-класслоадером типа. Для массива возвращается то же, что для типа его элементов. Для примитивов и void результатом всегда будет null.
👍10🔥4
👩‍💻 Знакомство с Java Instrumentation API & Java agent

Ждем вас на открытом уроке, где вы узнаете, что такое Java Instrumentation API и для чего нужны агенты. В онлайне изучим агент, позволяющий изменять код бизнес-классов для добавления дополнительных trace-логов для отладки приложения.

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

После занятия вы сможете писать и подключать Java-агенты самостоятельно, а также будете иметь представление о возможностях Java Instrumentation API.

Встречаемся 22 августа в 20:00 мск.

Спикер — Tech Lead в одном из крупнейших российских банков и кандидат технических наук.

👉 Запишитесь на вебинар и прокачайте свои навыки работы с Java: https://vk.cc/czjaBZ

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🔥42
Как узнать, является ли 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.
1👍23🔥31
👩‍💻 Обобщения в Java — что это и как эффективно с ними работать?

Ждем вас на открытом вебинаре, где мы познакомимся с одной из базовых тем языка Java — Обобщения (Generics).
Изучим, для чего они нужны, где они применяются в стандартной Java-библиотеке, а также как их можно использовать в своем коде.

Встречаемся 21 августа в 20:00 мск.

Спикер Александр Фисунов — Senior Kotlin Developer в SSP Software на проекте ВТБ, опытный Java-разработчик и кандидат технических наук.

👉 Регистрируйтесь прямо сейчас, чтобы не пропустить мероприятие: https://vk.cc/czoA2D

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

Reflection, рефлексия – это средства манипуляции данными на основе знания о структуре классов этих данных, инструменты метапрограммирования.

Класс Class<T> используется как точка входа в мир рефлекшена. Его экземпляры предоставляют саму метаинформацию о содержимом класса и основные методы для работы с ним. Все классы относящиеся Java Reflection находятся в пакетах java.lang и java.lang.reflect.

Экземпляр класса Class можно получить тремя способами:
🔘 Литералом .class;
🔘 Статическим фабричным методом Class.forName();
🔘 Методом getClass() экземпляров класса.

Использование Reflection API медленное и небезопасное. Оно позволяет ломать инвариантность состояний экземпляра, нарушать инкапсуляцию, и даже менять финальные поля.

Использовать рефлексию естественно в тестовом коде, в инструментах разработки, в фреймворках (особенно в связке с runtime-аннотациями). Рефлекшн в ординарном бизнес-коде обычно говорит о больших проблемах проектирования.

Нередко на интервью просят продемонстрировать пример использования рефлекшна. Один из самых близких для backend-разработчика примеров – инициализация классов-конфигураций в Spring Framework. Фреймворк с помощью рефлекшна сканирует внутренности таких классов. Поля и методы, помеченные специальными аннотациями, воспринимаются как объявления элементов экосистемы фреймворка.
👍17👏32
В чём отличия интерфейса от абстрактного класса?

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

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

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

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

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

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

Приходи на интенсив в Открытые школы Т1 для Java-разработчиков с опытом от года. Лучшие выпускники получат оффер от Т1 — крупнейшей ИТ-компании по версии RAEX 2023🔝 и уникальный карьерный фаст-трек до мидла в бигтехе.

В портфеле Холдинга Т1 800+ масштабных проектов и 70+ продуктов и услуг.

🧠 Всего за полгода мы выпустили 500+ специалистов. Участники присоединились к командам финтех-разработки и разработки ИТ-продуктов. Выпускников также ждут в юнитах облачных сервисов, развития ИИ-решений, интеграции и консалтинга.

Программа курса: spring framework; docker; синхронное и асинхронное взаимодействие, брокеры сообщений; паттерны, SOLID.

⌛️ Быстрое обучение: 1 месяц.
💻Гибкий формат: все этапы онлайн, занятия по вечерам.

Готов прокачаться вместе с экспертами индустрии? Тогда подавай заявку до 22 августа!

Старт интенсива — 28 августа.

Реклама. ООО "Т1". ИНН 7720484492.
👍53👏3😱1
Что если оба реализуемых интерфейса объявляют один и тот же метод?

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

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

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

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

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

Если различие в части throws, методы объявлены выбрасывающими разные типы исключений. Правила здесь те же, что для возвращаемых типов – работает ковариантность. Отличие лишь в том, что исключений примитивных типов не бывает, а даже для не являющихся родителем и наследником исключений всегда есть вариант, удовлетворяющий обоим – отсутствие выбрасываемых исключений вообще.
1👍176🔥5
⁉️ Spring Security — Alohomora для Java-разработчиков

Хотите освоить ключевой навык для Java-разработчика и обеспечить безопасность данных в своих проектах?

Ждем вас на открытом вебинаре 27 августа в 20:00 мск, где мы разберем:

- основы Spring Security;
- применение Spring Security для защиты данных и повышения безопасности проектов;
- применение магии «Alohomora» для открытия запертых дверей в мире безопасности.

Урок идеально подходит для Java- и Kotlin-разработчиков.

Встречаемся в преддверии старта курса «Разработчик на Spring Framework».
Все участники вебинара получат специальную цену на обучение!

👉 Регистрируйтесь прямо сейчас, чтобы не пропустить мероприятие: https://vk.cc/czBsnn

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

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

Для этого трюка необходимо прибегнуть к использованию 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);
🔥12👍51