Курс «Java Developer. Advanced» от OTUS — это глубокое погружение в устройство JVM, байткод, сборщики мусора, профилирование и оптимизацию в облаке.
Наши эксперты-практики покажут, как выбрать GC, снять дамп памяти и обнаружить утечки, как профилировать “горячие” места, настраивать интеграцию с Prometheus & Grafana и деплоить сервисы в Kubernetes.
🦾 Вы научитесь обосновывать выбор JVM-имплементации, анализировать heap-дампы, синхронизировать потоки, использовать Reactor и неблокирующие I/O, проектировать метрики и трассировку.
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4👍2🔥2
Как реализовать двусторонний обмен данными между потоками?
Вопрос, который зачастую дается в виде практической задачи. Конечно, результата можно добиться разными способами: парой атомарных переменных, критическими секциями, потокобезопасными коллекциями. Но полезно знать, что специально для этого случая в стандартной библиотеке java.util.concurrent есть простой класс Exchanger.
Класс содержит единственный метод V exchange(V x). Один поток передает в него данные, и встает в ожидание. Ожидание завершается, когда второй поток также приходит в метод exchange со своей порцией информации. В качестве результата вызова потоки получают данные друг друга.
На основе класса Exchanger удобно создавать пайплайны обработки данных. Первый поток выполняет свою часть обработки, и складывает результаты в буфер. В качестве буфера может работать любой многоразовый объект-контейнер. Когда он заполняется, следующий поток обменивает его на второй, пустой буфер. Таким образом два буфера используются поочередно, не выделяется лишний раз память и не нагружается GC. Далее из попарно обменивающихся буферами потоков может строиться длинная многопоточная цепочка обработки.
Java Guru🤓 #java
Вопрос, который зачастую дается в виде практической задачи. Конечно, результата можно добиться разными способами: парой атомарных переменных, критическими секциями, потокобезопасными коллекциями. Но полезно знать, что специально для этого случая в стандартной библиотеке java.util.concurrent есть простой класс Exchanger.
Класс содержит единственный метод V exchange(V x). Один поток передает в него данные, и встает в ожидание. Ожидание завершается, когда второй поток также приходит в метод exchange со своей порцией информации. В качестве результата вызова потоки получают данные друг друга.
На основе класса Exchanger удобно создавать пайплайны обработки данных. Первый поток выполняет свою часть обработки, и складывает результаты в буфер. В качестве буфера может работать любой многоразовый объект-контейнер. Когда он заполняется, следующий поток обменивает его на второй, пустой буфер. Таким образом два буфера используются поочередно, не выделяется лишний раз память и не нагружается GC. Далее из попарно обменивающихся буферами потоков может строиться длинная многопоточная цепочка обработки.
Java Guru🤓 #java
❤6🔥4👍1
Builder — это порождающий паттерн, который позволяет пошагово создавать сложные объекты. Вместо того чтобы создавать объект одним большим конструктором с множеством параметров, Builder организует процесс создания по частям, обеспечивая гибкость и читаемость кода.
Использование:
Преимущества:
Недостатки:
@javatasks #java
Please open Telegram to view this post
VIEW IN TELEGRAM
❤8👍4🔥1
Что такое функциональный интерфейс?
Так называется специальная разновидность интерфейса, который определяет тип-функцию, коллбэк.
Чтобы компилятор считал интерфейс функциональным, этот интерфейс должен добавлять единственный абстрактный метод. Вдобавок он может содержать любое количество дефолтных методов с телом. Переобъявление методов класса Object также игнорируется.
Никаких других ограничений на метод не накладывается: он не ограничен в типах аргументов и возвращаемого значения, может иметь любое название и список выбрасываемых исключений (checked и unchecked).
Даже при выполнении всех этих условий, никакие другие разновидности типов кроме interface не могут считаться функциональными интерфейсами.
Дополнительно функциональный интерфейс принято помечать аннотацией @FunctionalInterface. Наличие этой аннотации не необходимо, но оно даёт дополнительную валидацию: её присутствие на нефункциональном типе спровоцирует ошибку компиляции.
Типичные примеры функциональных интерфейсов: Callable, Supplier, Comparable.
@javatasks #java
Так называется специальная разновидность интерфейса, который определяет тип-функцию, коллбэк.
Чтобы компилятор считал интерфейс функциональным, этот интерфейс должен добавлять единственный абстрактный метод. Вдобавок он может содержать любое количество дефолтных методов с телом. Переобъявление методов класса Object также игнорируется.
Никаких других ограничений на метод не накладывается: он не ограничен в типах аргументов и возвращаемого значения, может иметь любое название и список выбрасываемых исключений (checked и unchecked).
Даже при выполнении всех этих условий, никакие другие разновидности типов кроме interface не могут считаться функциональными интерфейсами.
Дополнительно функциональный интерфейс принято помечать аннотацией @FunctionalInterface. Наличие этой аннотации не необходимо, но оно даёт дополнительную валидацию: её присутствие на нефункциональном типе спровоцирует ошибку компиляции.
Типичные примеры функциональных интерфейсов: Callable, Supplier, Comparable.
@javatasks #java
❤5🔥4👍2
Задачи с собеседований: Проверка, является ли бинарное дерево деревом поиска (middle)
— Как определить, является ли заданное бинарное дерево деревом поиска (BST)?
📌 Ключевые моменты:
- Бинарное дерево поиска (BST) — это бинарное дерево, в котором для каждого узла все значения в левом поддереве меньше значения узла, а все значения в правом поддереве больше.
- Для проверки можно использовать рекурсивный подход с отслеживанием допустимых диапазонов значений для каждого узла.
- Как изменить реализацию для работы с любыми типами данных в узлах дерева?
Реализация с числами в узлах на картинке👆
@javatasks #java
— Как определить, является ли заданное бинарное дерево деревом поиска (BST)?
- Бинарное дерево поиска (BST) — это бинарное дерево, в котором для каждого узла все значения в левом поддереве меньше значения узла, а все значения в правом поддереве больше.
- Для проверки можно использовать рекурсивный подход с отслеживанием допустимых диапазонов значений для каждого узла.
- Как изменить реализацию для работы с любыми типами данных в узлах дерева?
Реализация с числами в узлах на картинке
@javatasks #java
Please open Telegram to view this post
VIEW IN TELEGRAM
❤7👍3🔥2
Чем отличается final finally finalize?
Тем, что это даже синтаксически разные вещи. Как и вопрос о методах Object, это способ начать разговор.
finalize – метод-финализатор из Object.
final – модификатор, который применяется к переменным, полям, методам и классам. Переменная или поле становится неизменяемым и требует инициализации. Финальный метод нельзя переопределить в наследниках. Финальный класс не может иметь наследников вообще. Используется для создания хорошего API по принципу наименьших привилегий.
Когда в методе используется локальная переменная внешней области видимости, она обязана быть effectively final. В этом случае ключевое слово final необязательно, но значение всё равно не должно меняться.
finally – часть языковой конструкции try-catch-finally.
Любое исключение, выброшенное из блока try переводит исполнение в самый соответствующий ему catch (при наличии). Этим продиктована необходимость располагать блоки catch в строгом порядке, от типа исключения-наследника, к родителю. В случае multicatch тот же порядок должен соблюдаться и внутри одного catch. Больше примеров про порядок.
После выполнится блок finally. Выполняется он в любом случае, было исключение или нет. Типичное использование – освобождение ресурсов, обязательные завершающие действия.
Для требующих финализации классов («ресурсов») добавляется интерфейс AutoCloseable, повторяющийся код блока final выносится в метод close и вызывается неявно в конце try-with-resources. Если в этой конструкции присутствует и явный final, он будет выполнен после.
Java Guru🤓 #java
Тем, что это даже синтаксически разные вещи. Как и вопрос о методах Object, это способ начать разговор.
finalize – метод-финализатор из Object.
final – модификатор, который применяется к переменным, полям, методам и классам. Переменная или поле становится неизменяемым и требует инициализации. Финальный метод нельзя переопределить в наследниках. Финальный класс не может иметь наследников вообще. Используется для создания хорошего API по принципу наименьших привилегий.
Когда в методе используется локальная переменная внешней области видимости, она обязана быть effectively final. В этом случае ключевое слово final необязательно, но значение всё равно не должно меняться.
finally – часть языковой конструкции try-catch-finally.
Любое исключение, выброшенное из блока try переводит исполнение в самый соответствующий ему catch (при наличии). Этим продиктована необходимость располагать блоки catch в строгом порядке, от типа исключения-наследника, к родителю. В случае multicatch тот же порядок должен соблюдаться и внутри одного catch. Больше примеров про порядок.
После выполнится блок finally. Выполняется он в любом случае, было исключение или нет. Типичное использование – освобождение ресурсов, обязательные завершающие действия.
Для требующих финализации классов («ресурсов») добавляется интерфейс AutoCloseable, повторяющийся код блока final выносится в метод close и вызывается неявно в конце try-with-resources. Если в этой конструкции присутствует и явный final, он будет выполнен после.
Java Guru🤓 #java
❤6👍4🔥4
Чем отличаются checked и unchecked исключения?
Вопрос формулируют по-разному, суть вопроса – объяснение иерархии классов исключений. Подробно описано в документации.
Исключения бывают checked и unchecked. Checked требуется указывать в сигнатуре метода в разделе throws; перехватывать или добавлять в throws в вызывающем его методе. Unchecked можно добавить, но не обязательно, перехватывать не обязательно даже если указана в throws.
🔘 Throwable – базовый класс для всего что может быть использовано с оператором throw и в конструкции try-catch
🔘 RuntimeException – «нормальные» unchecked-исключения
🔘 Error – unchecked исключения, которые означают «серьезные проблемы» приложения. Не должны обрабатываться (хотя технически можно). Теоретически JVM может находиться в невалидном состоянии и не давать больше никаких гарантий
🔘 Exception (кроме RuntimeException) – checked исключения
@javatasks #java
Вопрос формулируют по-разному, суть вопроса – объяснение иерархии классов исключений. Подробно описано в документации.
Исключения бывают checked и unchecked. Checked требуется указывать в сигнатуре метода в разделе throws; перехватывать или добавлять в throws в вызывающем его методе. Unchecked можно добавить, но не обязательно, перехватывать не обязательно даже если указана в throws.
@javatasks #java
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5🔥4👍3
Зачем нужно ключевое слово default?
Изначально (с Java 1.5) это слово использовалось для объявления дефолтного значения элементов аннотации.
В Java 8 вместе с лямбдами и стримами появилась острая необходимость дополнить стандартные интерфейсы новыми методами. Никто естественно не собирался ломать обратную совместимость, и было предложено добавить методы по умолчанию.
Теперь добавление ключевого слова default к методу интерфейса позволяет добавить ему тело. Все новые методы старых интерфейсов снабжаются дефолтной реализацией.
В реализации такого метода его дефолтный вариант вызывается тем же синтаксисом, что и внешний класс из вложенного: InterfaceName.super.methodName().
Методы по умолчанию подошли еще на шаг к введению в Java беспроблемной версии множественного наследования – примесям (mixin). Интерфейс не может иметь состояния, поэтому полноценные примеси всё ещё недоступны.
@javatasks #java
Изначально (с Java 1.5) это слово использовалось для объявления дефолтного значения элементов аннотации.
В Java 8 вместе с лямбдами и стримами появилась острая необходимость дополнить стандартные интерфейсы новыми методами. Никто естественно не собирался ломать обратную совместимость, и было предложено добавить методы по умолчанию.
Теперь добавление ключевого слова default к методу интерфейса позволяет добавить ему тело. Все новые методы старых интерфейсов снабжаются дефолтной реализацией.
В реализации такого метода его дефолтный вариант вызывается тем же синтаксисом, что и внешний класс из вложенного: InterfaceName.super.methodName().
Методы по умолчанию подошли еще на шаг к введению в Java беспроблемной версии множественного наследования – примесям (mixin). Интерфейс не может иметь состояния, поэтому полноценные примеси всё ещё недоступны.
@javatasks #java
👍7🔥4❤1
В каком порядке указываются модификаторы?
Правила применения модификаторов поля описаны в JLS 8.3.1:
🔘 Нельзя указывать один модификатор дважды;
🔘 Нельзя использовать несколько модификаторов доступа одновременно.
Порядок указания вообще свободный, но обычно используется следующий:
@Аннотации, доступ,
Требования для модификаторов метода находятся в JLS 8.4.3:
🔘 Те же требования, что и к полю;
🔘 Совместно с abstract кроме аннотаций можно использовать только protected или public;
🔘 native метод не может использовать strictfp.
И так же не требуется, но рекомендуется использовать такой порядок:
@Аннотации, доступ,
Java Guru🤓 #java
Правила применения модификаторов поля описаны в JLS 8.3.1:
Порядок указания вообще свободный, но обычно используется следующий:
@Аннотации, доступ,
static final transient volatile
Требования для модификаторов метода находятся в JLS 8.4.3:
И так же не требуется, но рекомендуется использовать такой порядок:
@Аннотации, доступ,
abstract static final synchronized native strictfp
Java Guru🤓 #java
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10🔥6❤1
Фасад — это структурный паттерн, который предоставляет унифицированный интерфейс для работы с набором сложных подсистем. Он скрывает сложность системы и упрощает взаимодействие с ней, предоставляя более простой и понятный API для клиента.
Использование:
Преимущества:
Недостатки:
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥10❤6👍2
Что такое короткое замыкание логического оператора?
Логические операторы || и && лево-ассоциативны, то есть их параметры вычисляются слева направо. Если первое значение оказалось true в || или false в && – конечный результат уже предрешен, он будет тем же. В этом случае происходит так называемое «короткое замыкание» (short-circuiting) – оставшийся второй аргумент не вычисляется за ненадобностью.
Эту особенность иногда удобно эксплуатировать, например для проверки на null в одну строку:
Но иногда такая ситуация влечет за собой неожиданные плавающие баги, если второй аргумент – не переменная, а функция с побочным эффектом. Для этой ситуации введены версии операторов без короткого замыкания: | и &. Это логические вариации «битового и» и «битового или».
Вдобавок доступен оператор «исключающее или» ^. Он почти никогда не используется для булевых параметров, потому что абсолютно эквивалентен более интуитивно понятному !=. Другие битовые операторы для логических аргументов недоступны.
Java Guru🤓 #java
Логические операторы || и && лево-ассоциативны, то есть их параметры вычисляются слева направо. Если первое значение оказалось true в || или false в && – конечный результат уже предрешен, он будет тем же. В этом случае происходит так называемое «короткое замыкание» (short-circuiting) – оставшийся второй аргумент не вычисляется за ненадобностью.
Эту особенность иногда удобно эксплуатировать, например для проверки на null в одну строку:
return param != null && param.getBoolMember();
Но иногда такая ситуация влечет за собой неожиданные плавающие баги, если второй аргумент – не переменная, а функция с побочным эффектом. Для этой ситуации введены версии операторов без короткого замыкания: | и &. Это логические вариации «битового и» и «битового или».
Вдобавок доступен оператор «исключающее или» ^. Он почти никогда не используется для булевых параметров, потому что абсолютно эквивалентен более интуитивно понятному !=. Другие битовые операторы для логических аргументов недоступны.
Java Guru🤓 #java
❤8👍4🔥1
🦾 Вас ждет огромное количество практики и реальные кейсы: настройка окружения, базовые алгоритмы, синтаксис Java, Spring и Docker. Мы покажем, почему диплом OTUS ценят HR в крупных компаниях.
Если вы сисадмин, тестировщик, аналитик или просто хотите освоить программирование с нуля — этот курс для вас.
Мы научим создавать серверные веб-приложения, работать с PostgreSQL, Kafka и Kubernetes, формировать портфолио и готовить резюме под Middle-Java-Dev.
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4👍2🔥2
Перечислите целочисленные битовые операторы
Во-первых, стоит освежить знания о бинарном представлении целых знаковых чисел. В Java используется подход two's complement – для значения 0 все биты нули, при переполнении максимального значения на 1 получается минимальное.
Бинарные битовые операторы &, | и ^ действуют очевидным образом: выполняют побитовые «И», «ИЛИ» и «исключающее ИЛИ» (XOR) соответственно. Здесь особенно интересен XOR:
Применение к значению «исключающего или» с одним и тем же параметром два раза дает то же значение. За счет этого его можно использовать как простейшее шифрование, аргумент выступит ключом;
С помощью XOR реализуется XOR-обмен – алгоритм обмена значениями переменных без дополнительной памяти и без риска переполнения. Это также один из популярных вопросов для собеседования.
Унарный оператор битового отрицания (дополнения) ~. Эквивалентен «исключающему или» с самим собой – все биты инвертируются. ~x эквивалентно -x-1. ~0 == -1.
Битовые сдвиги: левый << правый знаковый >> и правый беззнаковый >>>. Левый операнд – что сдвигать, правый – на сколько битов.
Второй параметр, дистанция сдвига, должен быть не больше доступных разрядов – 31 для int и 63 для long. Если передано значение больше – используются младшие 5 и 7 битов соответственно. То есть для int переменной x << 33 эквивалентно x << 2.
a << b эквивалентно умножению a на 2 в степени b.
a >> b совпадает с делением на 2 в степени b, с округлением вниз. Для положительных a то же что a/pow(2,b). Для не делящихся нацело на pow(2,b) отрицательных это a/pow(2,b)-1.
Беззнаковый сдвиг вправо трактует число не как two's complement, а как беззнаковое. То есть Integer.MIN_VALUE будет сдвинут так, как будто это сдвигается число на 1 большее чем Integer.MAX_VALUE.
Беззнакового сдвига влево не существует, потому что он совпадал бы со знаковым сдвигом, и был бы избыточным.
Java Guru🤓 #java
Во-первых, стоит освежить знания о бинарном представлении целых знаковых чисел. В Java используется подход two's complement – для значения 0 все биты нули, при переполнении максимального значения на 1 получается минимальное.
Бинарные битовые операторы &, | и ^ действуют очевидным образом: выполняют побитовые «И», «ИЛИ» и «исключающее ИЛИ» (XOR) соответственно. Здесь особенно интересен XOR:
Применение к значению «исключающего или» с одним и тем же параметром два раза дает то же значение. За счет этого его можно использовать как простейшее шифрование, аргумент выступит ключом;
С помощью XOR реализуется XOR-обмен – алгоритм обмена значениями переменных без дополнительной памяти и без риска переполнения. Это также один из популярных вопросов для собеседования.
Унарный оператор битового отрицания (дополнения) ~. Эквивалентен «исключающему или» с самим собой – все биты инвертируются. ~x эквивалентно -x-1. ~0 == -1.
Битовые сдвиги: левый << правый знаковый >> и правый беззнаковый >>>. Левый операнд – что сдвигать, правый – на сколько битов.
Второй параметр, дистанция сдвига, должен быть не больше доступных разрядов – 31 для int и 63 для long. Если передано значение больше – используются младшие 5 и 7 битов соответственно. То есть для int переменной x << 33 эквивалентно x << 2.
a << b эквивалентно умножению a на 2 в степени b.
a >> b совпадает с делением на 2 в степени b, с округлением вниз. Для положительных a то же что a/pow(2,b). Для не делящихся нацело на pow(2,b) отрицательных это a/pow(2,b)-1.
Беззнаковый сдвиг вправо трактует число не как two's complement, а как беззнаковое. То есть Integer.MIN_VALUE будет сдвинут так, как будто это сдвигается число на 1 большее чем Integer.MAX_VALUE.
Беззнакового сдвига влево не существует, потому что он совпадал бы со знаковым сдвигом, и был бы избыточным.
Java Guru🤓 #java
🔥6❤4👍3
23 июля(уже завтра!) в 19:00 по мск приходи онлайн на открытое собеседование, чтобы посмотреть на настоящее интервью на Middle Java-разработчика.
Как это будет:
Это бесплатно. Эфир проходит в рамках менторской программы от ШОРТКАТ для Java-разработчиков, которые хотят повысить свой грейд, ЗП и прокачать скиллы.
Переходи в нашего бота, чтобы получить ссылку на эфир → @shortcut_sh_bot
Реклама.
О рекламодателе
Please open Telegram to view this post
VIEW IN TELEGRAM
❤3👍2🔥2
Как узнать, является ли 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
В 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
❤6👍5🔥3
Чем анонимный внутренний класс отличается от лямбды?
Лямбда-выражение имеет более легковесный синтаксис. Не нужно явно указывать тип функционального интерфейса, который лямбда реализует – он автоматически выведется из контекста. Лямбда-выражения добавлены в язык в первую очередь как синтаксический сахар.
С другой стороны, у класса есть поля. Экземпляр анонимного класса сохраняет свое состояние между вызовами, и меняет его при необходимости. Для лямбды доступен лишь захват и effectively final использование внешних переменных.
Лямбдой реализуется только функциональный интерфейс. Функциональный интерфейс – это тип с единственным абстрактным методом. Анонимным классом же можно расширить любой расширяемый класс или реализовать интерфейс с любым количеством абстрактных методов.
Анонимный класс создает новый скоуп, лямбда работает в текущем. Это значит, что объявление переменной с именем, которое уже используется снаружи, в лямбде вызовет ошибку компиляции «variable is already defined», в анонимном классе скроет (shadowing) внешнюю переменную.
С точки зрения реализации JVM, для лямбды не создается дополнительного .class файла, как это происходит для анонимного класса. Соответственно, не происходит и обычной загрузки и верификации класса. Вместо этого используется механизм invokedynamic и класс генерируется на лету с помощью LambdaMetafactory. Так что лямбда-выражения обычно работают быстрее.
Java Guru🤓 #java
Лямбда-выражение имеет более легковесный синтаксис. Не нужно явно указывать тип функционального интерфейса, который лямбда реализует – он автоматически выведется из контекста. Лямбда-выражения добавлены в язык в первую очередь как синтаксический сахар.
С другой стороны, у класса есть поля. Экземпляр анонимного класса сохраняет свое состояние между вызовами, и меняет его при необходимости. Для лямбды доступен лишь захват и effectively final использование внешних переменных.
Лямбдой реализуется только функциональный интерфейс. Функциональный интерфейс – это тип с единственным абстрактным методом. Анонимным классом же можно расширить любой расширяемый класс или реализовать интерфейс с любым количеством абстрактных методов.
Анонимный класс создает новый скоуп, лямбда работает в текущем. Это значит, что объявление переменной с именем, которое уже используется снаружи, в лямбде вызовет ошибку компиляции «variable is already defined», в анонимном классе скроет (shadowing) внешнюю переменную.
С точки зрения реализации JVM, для лямбды не создается дополнительного .class файла, как это происходит для анонимного класса. Соответственно, не происходит и обычной загрузки и верификации класса. Вместо этого используется механизм invokedynamic и класс генерируется на лету с помощью LambdaMetafactory. Так что лямбда-выражения обычно работают быстрее.
Java Guru🤓 #java
🔥12❤4👍4🌭1
Как объявить переменное количество аргументов метода?
Для этого используется аргумент-массив. В нем может находиться любое количество элементов. Еще с Java 5 для этого случая добавился синтаксический сахар: Variable-length argument (vararg). Три точки ... ставятся между типом и именем переменной, и становится можно передать любое количество аргументов, не упаковывая их в массив.
На уровне байткода применение массива и варарга не отличаются: vararg-параметр Foo... превращается в параметр-массив Foo[], на этапе вызова подставляется неявное инстанцирование и заполнение массива.
Чтобы избежать неоднозначностей, на vararg наложено ограничение: им может быть только один последний аргумент.
Vararg, как массив, может быть пустым. Иногда это приводит к неочевидному поведению. Допустим, имеем две перегрузки метода с аргументами int... и float.... Вызов такого метода без параметров попадает в вариант с int, как с более специфичным типом. Наличие же перегрузки с несовместимыми типами, например int... и boolean..., приводит при вызове к ошибке компиляции «Ambiguous method call».
Когда типом варарга используется generic-параметр, возникает warning «Possible heap pollution from parameterized vararg type». Вам нужно убедиться, что вы понимаете в чем этот риск, что ваш код не приводит к heap pollution, и уведомить об этом компилятор аннотацией @SafeVarargs.
Java Guru🤓 #java
Для этого используется аргумент-массив. В нем может находиться любое количество элементов. Еще с Java 5 для этого случая добавился синтаксический сахар: Variable-length argument (vararg). Три точки ... ставятся между типом и именем переменной, и становится можно передать любое количество аргументов, не упаковывая их в массив.
На уровне байткода применение массива и варарга не отличаются: vararg-параметр Foo... превращается в параметр-массив Foo[], на этапе вызова подставляется неявное инстанцирование и заполнение массива.
Чтобы избежать неоднозначностей, на vararg наложено ограничение: им может быть только один последний аргумент.
Vararg, как массив, может быть пустым. Иногда это приводит к неочевидному поведению. Допустим, имеем две перегрузки метода с аргументами int... и float.... Вызов такого метода без параметров попадает в вариант с int, как с более специфичным типом. Наличие же перегрузки с несовместимыми типами, например int... и boolean..., приводит при вызове к ошибке компиляции «Ambiguous method call».
Когда типом варарга используется generic-параметр, возникает warning «Possible heap pollution from parameterized vararg type». Вам нужно убедиться, что вы понимаете в чем этот риск, что ваш код не приводит к heap pollution, и уведомить об этом компилятор аннотацией @SafeVarargs.
Java Guru🤓 #java
👍10❤3🔥2
Что будет при вызове /api/customers/{5}, если записи c id 5 нет
Anonymous Quiz
27%
HTTP 404 (Not Found) с телом ответа null
52%
HTTP 200 (OK) с телом ответа null
6%
NullPointerException
8%
HTTP 500 (Internal Server Error)
7%
HTTP 400 (Bad Request)
🔥6👍5❤1
This media is not supported in your browser
VIEW IN TELEGRAM
Технологии, железо и роботы на Yandex Robotics Day уже 16 августа!
На складах Маркета, Леманы Про, Перекрестка, Лавки и других компаний работают роботы Яндекса, которые помогают быстро сканировать товары, собирать посылки и перемещать заказы. Чтобы все функционировало быстро и точно, специалисты Яндекс Роботикс постоянно улучшают их.
16 августа в Москве пройдет митап, на котором они расскажут, как именно это делают:
— Серёжа Стариков выступит с докладом про коммуникационную платформу Yandex Robotics и ее применение в Yandex RMS
— Дима Мовчан объяснит, как команда создает умную роборуку с помощью imitation learning и RL
— Максим Пшибло расскажет, как с помощью Yandex Robotics Management System управлять несколькими роботами и какие алгоритмы необходимы этой системе
Кроме докладов в программе презентация нового робота, выставка тех, которые уже вовсю работают на складах, нетворкинг и неформальное афтепати с экспертами Яндекс Роботикс.
Регистрируйтесь и зовите коллег!
Реклама. ООО "ЯНДЕКС МАРКЕТ". ИНН 9704254424.
На складах Маркета, Леманы Про, Перекрестка, Лавки и других компаний работают роботы Яндекса, которые помогают быстро сканировать товары, собирать посылки и перемещать заказы. Чтобы все функционировало быстро и точно, специалисты Яндекс Роботикс постоянно улучшают их.
16 августа в Москве пройдет митап, на котором они расскажут, как именно это делают:
— Серёжа Стариков выступит с докладом про коммуникационную платформу Yandex Robotics и ее применение в Yandex RMS
— Дима Мовчан объяснит, как команда создает умную роборуку с помощью imitation learning и RL
— Максим Пшибло расскажет, как с помощью Yandex Robotics Management System управлять несколькими роботами и какие алгоритмы необходимы этой системе
Кроме докладов в программе презентация нового робота, выставка тех, которые уже вовсю работают на складах, нетворкинг и неформальное афтепати с экспертами Яндекс Роботикс.
Регистрируйтесь и зовите коллег!
Реклама. ООО "ЯНДЕКС МАРКЕТ". ИНН 9704254424.
❤5👍1