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
Чем отличается перегрузка от переопределения?

Полиморфизм – соль ООП. Перегрузка (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. Ее отсутствие допускается, но компиляция не перегружающего метода с такой аннотацией приведет к ошибке.

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

Статические методы нельзя переопределить, можно только перегрузить.


Java Guru🤓 #java
👍146🔥4
Какое регулярное выражение соответствует строке, содержащей только цифры и имеющей длину от 3 до 5 символов?
Anonymous Quiz
50%
^[0-9]{3,5}$
14%
^[\d][3,5]$
16%
\d(3,5}
10%
*[0-9]{3.5}
9%
\d{3,5}/
🔥11👍54
Когда 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.


Java Guru🤓 #java
🔥72
Как узнать, является ли 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.


Java Guru🤓 #java
🔥8👍42
Что вернётся, если отправить GET-запрос на /test?
👍5🔥2
🔥10👍6
Что такое Reflection и как его использовать?

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

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

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

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

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

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


Java Guru🤓 #java
Please open Telegram to view this post
VIEW IN TELEGRAM
👍115🔥5
В чём отличия интерфейса от абстрактного класса?

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

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

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

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

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

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


Java Guru🤓 #java
👍16🔥73
Что будет результатом запуска кода?
👍5🔥2
👍6🔥2
Что если оба реализуемых интерфейса объявляют один и тот же метод?

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

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

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

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

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

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


Java Guru🤓 #java
👍10🔥32
Как изменить значение приватного финального поля?

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

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


Java Guru🤓 #java
👍9🔥42
Приведите примеры операций со стримами

Самые часто используемые

Java Guru🤓 #java
🔥16👍85
При вызове метода executeTask() три раза, сколько экземпляров TaskProcessor будет создано?
🔥5👍4
При вызове метода 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