Библиотека джависта | Java, Spring, Maven, Hibernate
24.9K subscribers
1.86K photos
38 videos
42 files
2.64K links
Все самое полезное для Java-разработчика в одном канале.

Список наших каналов: https://yangx.top/proglibrary/9197

Обратная связь: @proglibrary_feedback_bot

По рекламе: @proglib_adv

РКН: https://gosuslugi.ru/snet/67a5bbda1b17b35b6c1a55c4
加入频道
Как прочитать криптографический ключ?

KeyFactory – основной класс платформы Java для работы с криптографическими ключами. Набор реализаций для этой фабрики подключается с помощью механизма SPI.

Существует большое разнообразие алгоритмов шифрования: DSA, RSA, и другие. Строка-название нужного алгоритма поставляется в фабрику ключей при её создании.

KeyFactory занимается конвертацией спецификации ключа в сам публичный или приватный ключ, и обратно.

Спецификация, объект интерфейса KeySpec, – входные данные ключа. Это может быть например модуль и экспонента приватного ключа RSA.

Сами внутренние представления ключей реализуют интерфейсы PublicKey и PrivateKey – наследники общего Key.

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

• Классы текущего пакета доступны без импорта. Если импортируется другой класс, совпадающий с классом-соседом по пакету – сосед перекрывается. Будет использован импортированный класс, без ошибки.

• Если в class-файле существует несколько разных классов с одинаковыми именами, объявленных здесь же или импортированных – это приводит к ошибке компиляции.

• Импортировать один и тот же класс несколько раз допускается. Будет всего лишь warning о неиспользуемом импорте.

• Для статических импортов констант действуют те же правила. Обычные и статические импорты не конфликтуют друг с другом – для выбора достаточно контекста использования.

• Чтобы применять несколько классов/констант с одинаковыми именами в одном файле, придется обойтись без импортов. Нужно будет обращаться по их полным именам, с указанием пакета.
Как сериализация работает с наследованием?

Когда Serializable класс имеет цепочку родителей, пока эти родители тоже Serializable, десериализация объекта идет от родителя к наследнику, в обход конструктора. Вместо него вызываются методы readObject (readObjectNoData). Но как только встречается первый предок, не реализующий интерфейс Serializable, инициализация для него возвращается в нормальное русло – вместо readObject вызывается конструктор без аргументов. Если такого конструктора нет, или он объявлен private, исполнение выбросит InvalidClassException.

При сериализации несериализуемые предки просто игнорируются.

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

Популярный вопрос на тему – как когда сериализуешь объект класса-наследника, избежать сериализации его родительской части. Единственный способ добиться этого – кастомизировать сериализационную форму, определив собственную реализацию writeObject(), либо используя интерфейс Externalizable.

Открытость класса для наследования делает неприменимым паттерн serialization proxy (который рассмотрим позднее).
Вы профи в своём деле? Мы хорошо за это заплатим. Ищем экспертов для проведения мероприятия в Москве 22 и 23 мая. Темы следующие:

- Архитектура программного обеспечения
- Подходы к решению алгоритмических задач с собеседований Google и Яндекс
- Базы данных: модели, миграции, тестирование
- Практикум по рефакторингу

За один день платим от 20 до 30 тыс. ₽ (в зависимости от опыта и вовлеченности). Отклики с резюме кидайте сюда: @proglib_expert_bot
Вы наверняка заметили, что мы регулярно проводим опросы, чтобы соответствовать вашим запросам и интересам. Знаем, что нас читают не только новички – многие подписчики уже стали миддлами и даже сеньорами. Если чувствуете, что переросли middle-уровень, пора задуматься о создании собственного полноценного проекта – не на одни выходные.

Для такой задачи нужно широкое видение процесса разработки и архитектуры информационных систем. На одной интуиции можно набить шишек, а книжки по таким вопросам достаточно быстро устаревают. Обратите внимание на страницу курса Архитектор ИТ https://proglib.io/w/ebb18c5f

На странице можно почерпнуть сведения о том, какие знания нужны, и составить собственную программу-максимум. Или сэкономить время и воспользоваться учебным планом GeekBrains – благо уже есть площадка с контентом, приглашенные эксперты-практики и 4 курсовых проекта с поддержкой крупных компаний.
Что можно делать с переменной хранящей null?

Во-первых, если переменная не финальная, использовать как L-value этого типа – присваивать новое значение.

Во-вторых, то же, что со значением null, но с учетом типа:
🔘 Сравнивать с null или переменной этого же класса;
🔘 Приводить к типу-родителю (upcast) или типу-наследнику (downcast), учитывая границы generic-параметров при наличии;
🔘 Обращаться к членам экземпляра и получать NullPointerException;
🔘 Применять instanceof и получать false
🔘 Использовать как параметр для методов и других совместимых с типом операторов

В-третьих, можно обращаться к статическим членам класса. В вопросе подразумевается именно эта интересная часть. Это безопасно, NullPointerException не возникнет, но для упрощения отладки и из-за отсутствия переопределения статических членов рекомендуется так не делать. Вместо этого обращайтесь к статике явно через имя класса, либо неявно, добавив для класса import static.
Что такое static?

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

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

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

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

Статический импорт (static import) импортирует статические члены классов в .java-файл.
#вопросы_с_собеседований
Чем отличаются методы Thread.sleep() и Thread.yield()?
Метод yield() служит причиной того, что поток переходит из состояния работающий (running) в состояние работоспособный (runnable), давая возможность другим потокам активизироваться. Но следующий выбранный для запуска поток может и не быть другим.

Метод sleep() вызывает засыпание текущего потока на заданное время, состояние изменяется с работающий (running) на ожидающий (waiting).
Beginning Jakarta EE Web Development (2020)
Автор: Luciano Manelli
Количество страниц: 424

Начните создавать веб-приложения на основе Java прямо сейчас, даже если вы новичок в Java. Эта всеобъемлющая и основанная на примерах книга - все, что вам нужно для разработки динамических веб-приложений на основе Java с использованием JSP, подключения к базам данных с помощью JSF и их практического использования с помощью популярного веб-сервера Java с открытым исходным кодом, Apache Tomcat.

Скачать книгу
Крупнейший сервис Телеграм-аналитики TGStat проводит исследование аудитории Телеграма. Опрос анонимный, занимает не больше пяти-семи минут, почти везде просто клики по вариантам ответа. В результате статистика по каналам станет точнее, а жизнь — проще. Давайте поможем: https://tgstat.ru/research
new Integer(128) == 128?

Для всех классов-оберток над примитивами кроме Float и Double работает механизм кэширования. Некоторые значения создаются на этапе инициализации класса, и переиспользуются когда объект создается не оператором new (например с помощью valueOf).

Кэшируемые значения – оба возможных Boolean, Character до 'u007f' (127) и все целые числа от -128 до 127 включительно. С Java 7 верхнюю границу для Integer можно увеличить параметром java.lang.Integer.IntegerCache.high.

Значения кэшируются и во многих других встроенных классах: BigDecimal, Currency, пустые коллекции. Детали можно узнавать из исходников и документаций, так как эти кэши реализованы не на уровне JVM а в коде классов.

В конкретно этом примере скрыт еще один подвох: объект класса-обертки сравнивается с примитивом. Это приводит к анбоксингу и сравнению значений. И ответ на вопрос – да.
Что такое enum?

enum
– тип-перечисление. Бывает много разных формулировок вопроса, все они сводятся к разговору о перечислениях вообще. Технически это финальный класс со статическими финальными полями-экземплярами. enum Foo всегда неявно наследуется от Enum<Foo> – то есть перечислением нельзя расширить другой класс, но всё еще можно реализовать интерфейсы. Из-за generic-параметра разные перечисления не имеют общего предка кроме Object.

Является Comparable (сравнивается позиция по порядку объявления значений) и Serializable (сериализуется только имя константы).

Имеет только заранее заданный набор значений. Значения неявно public static final и это нельзя переопределить. Для инициализации констант действуют все правила статической типизации.

Копии элементов перечисления не создаются даже при десериализации. Вот почему Effective Java предлагает использовать для сериализуемого синглтона enum.

Экземпляры хранят свойства name и ordinal – имя и порядковый номер константы. Статический метод values вернет список всех констант, valueOf – константу по имени. Спецификация.

Финализация и клонирование перечислений запрещены.
Под каким типом хранить период времени?

В стандартной библиотеке современных версий Java для этих целей есть два класса:

Period – календарный период. Количество дней, месяцев и лет. Одним днем здесь считается день в терминах ZonedDateTime.

Duration – длительность времени. Количество наносекунд, секунд, минут, часов, и тоже дней. Здесь один день – ровно 24 часа.

Оба класса реализуют общий интерфейс TemporalAmount – период времени вообще. Оба иммутабельны, и как следствие, потокобезопасны. Любая модифицирующая операция вроде plusX() возвращает новый экземпляр с измененным значением.

Экземпляры обоих классов могут быть созданы из значений отдельных компонентов, из двух моментов времени методом between, или из строки. Строковое представление Duration: "P2DT3H4M", Period: "P1Y2M3D".

До Java 8 основным способом хранения периода были числовые примитивы. В этом подходе есть много недостатков, среди которых в первую очередь неограниченность значений и ненаглядность. Чтобы в Java 8+ получить период числом, используется метод between() нужного элемента енама ChronoUnit.
Как реализовать собственный стрим?

Любой стрим определяется его сплитератором. Spliterator – это специальный разделяемый внутренний итератор.

Есть много способов получить готовый сплитератор или стрим, но чтобы создать полностью свою специфическую логику перебора элементов, придется написать собственный сплитератор.

Поток создается из сплитератора одним из статических методов класса StreamSupport. Вызов его методов осуществляется самим фреймворком. Вкратце его работа выглядит так:
• Элементы перебираются методом tryAdvance, пока он не выдаст false. Через параметр action к элементу применяются последующие операции.
• При применении промежуточных и терминальных операций учитываются характеристики потока, изначально задаваемые методом characteristics.
• Когда обработка стрима распараллеливается, методом trySplit от начала последовательности элементов «откусывается» часть, и возвращается завернутой в новый сплитератор. Текущий продолжает идти по оставшемуся хвосту. В идеале, по возможности эта часть – половина элементов потока. Если разделить уже нельзя, возвращается null.

Подробно и доступно последовательность действий для реализации описана в статье на хабре.
Продолжаем конкурс на самый интересный контент в телеграм-каналах Proglib!
Призовой фонд — 280 тысяч рублей.
Срок окончания конкурса -- 15 мая

Автор лучшего поста в отдельно взятом канале получает 20 тысяч рублей.
Мы упростили конкурс — теперь вам достаточно найти интересную и актуальную статью 2020-2021 года, написать к ней небольшой анонс (до 700 знаков) и прислать нам, тем не менее ваши идеи по другим форматам только добавляют + в общий зачет. Авторство можем указать по вашему желанию. В канале @progbook предлагаем отправлять рецензии на новые книги и старые актуальные.

Полный список каналов:
https://yangx.top/progbook
https://yangx.top/proglibrary
https://yangx.top/pyproglib
https://yangx.top/frontendproglib
https://yangx.top/javaproglib
https://yangx.top/dsproglib
https://yangx.top/phpproglib
https://yangx.top/cppproglib
https://yangx.top/mobileproglib
https://yangx.top/goproglib
https://yangx.top/csharpproglib
https://yangx.top/devopsslib
https://yangx.top/testerlib
https://yangx.top/hackproglib

Все посты будут с лайками и дизлайками и хэштегом #proglib_contest. Ссылки мы будем прогонять через наш сокращатель, будут браться в расчет лайки, дизлайки, охваты, клики по ссылкам. Выиграет тот кто наберёт больше всего лайков/охватов/кликов по ссылкам в публикации. Присылайте посты боту @proglib_contest_bot с указанием, на какой канал идет публикация. Юридическая информация здесь.
#вопросы_с_собеседований
Существует ли способ решения проблемы race condition?
Распространённые способы решения:

☕️ Использование локальной копии — копирование разделяемой переменной в локальную переменную потока. Этот способ работает только тогда, когда переменная одна и копирование производится атомарно (за одну машинную команду), использование volatile.
☕️ Синхронизация - операции над разделяемым ресурсом происходят в синхронизированном блоке (при использовании ключевого слова synchronized).
☕️ Комбинирование методов - вышеперечисленные способы можно комбинировать, копируя «опасные» переменные в синхронизированном блоке. С одной стороны, это снимает ограничение на атомарность, с другой — позволяет избавиться от слишком больших синхронизированных блоков.

Очевидных способов выявления и исправления состояний гонки не существует. Лучший способ избавиться от гонок — правильное проектирование многозадачной системы.
Допустим, ты уверенно чувствуешь себя в математике и Java, есть диплом бакалавра или специалиста, с интересом смотришь на сферу анализа данных. Таких людей на рынке труда не хватает. До 30 июня ты можешь проверить свои силы и подать заявку для поступления на магистерскую программу «Промышленный анализ данных в ритейле».

Программа разработана совместно X5 и МФТИ. Не для ленивых: 80+ реальных кейсов и 3 тыс. часов прокачивания навыков в практическом Data Science на примере ритейла.

Обучающиеся смогут оформить стажировку или даже трудоустроиться в X5 Технологии и получать от компании повышенную стипендию. Презентация кафедры, учебная программа, и условия поступления здесь: https://mipt.x5.ru/
Создаем компактную среду выполнения с jlink

В Java 9 появился новый инструмент под названием jlink. Этот простой инструмент командной строки позволяет создавать собственные среды выполнения только с теми модулями, что нужны нашему приложению. Например, с помощью следующей команды мы создадим среду выполнения, содержащую только модуль java.base:

jlink --add-modules java.base --output javabasert

Подробнее на множестве примеров разобрано здесь:
https://proglib.io/w/454a3607

#proglib_contest