[Совет по Java #031]
Тема: ArrayList.subList() не копирует данные, а создает view на исходный список.
Проблема: Метод subList(int fromIndex, int toIndex) возвращает не новый независимый список, а проекцию (view) исходного ArrayList.
Все операции над view отображаются на исходный список, и наоборот. Однако при структурной модификации исходного списка (добавление или удаление элементов) после создания view, последний становится некорректным. При последующей операции над sublist выбрасывается ConcurrentModificationException.
Это частая ошибка: разработчик создает sublist, затем изменяет оригинал и пытается использовать view, получая исключение. Кроме того, изменения sublist (например, clear()) неожиданно модифицируют оригинальный список, что может привести к трудноотлаживаемым багам.
Решение: Если нужен независимый список, скопируйте sublist в новую коллекцию: new ArrayList<>(list.subList(1, 5)). Если работаете с view, избегайте структурных модификаций исходного списка. Для read-only операций sublist эффективен и удобен.
Объяснение: subList() возвращает объект внутреннего класса SubList, который хранит ссылку на исходный ArrayList и смещения. Все операции делегируются исходному списку с проверкой границ. При создании SubList запоминается счетчик модификаций (modCount) оригинала. При каждой операции view сравнивает текущий modCount оригинала с запомненным. Если они различаются (оригинал был структурно изменен), выбрасывается ConcurrentModificationException.
Структурной модификацией считается изменение размера списка (add, remove, clear). Замена элементов через set() к ней не относится. Эта защита предотвращает неконсистентное состояние, когда view указывает на неправильные диапазоны.
#Java #советы
Тема: ArrayList.subList() не копирует данные, а создает view на исходный список.
Проблема: Метод subList(int fromIndex, int toIndex) возвращает не новый независимый список, а проекцию (view) исходного ArrayList.
Все операции над view отображаются на исходный список, и наоборот. Однако при структурной модификации исходного списка (добавление или удаление элементов) после создания view, последний становится некорректным. При последующей операции над sublist выбрасывается ConcurrentModificationException.
Это частая ошибка: разработчик создает sublist, затем изменяет оригинал и пытается использовать view, получая исключение. Кроме того, изменения sublist (например, clear()) неожиданно модифицируют оригинальный список, что может привести к трудноотлаживаемым багам.
Решение: Если нужен независимый список, скопируйте sublist в новую коллекцию: new ArrayList<>(list.subList(1, 5)). Если работаете с view, избегайте структурных модификаций исходного списка. Для read-only операций sublist эффективен и удобен.
public class SubListViewExample {
public static void main(String[] args) {
List<Integer> original = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8));
// Создаем view на подсписок
List<Integer> sub = original.subList(2, 5);
System.out.println("Sublist (view): " + sub); // [3, 4, 5]
//Опасность 1: изменение view меняет оригинал
sub.set(0, 99);
sub.add(100);
System.out.println("Original after modifying view: " + original);
// [1, 2, 99, 4, 5, 100, 6, 7, 8] — оригинал изменился!
//Опасность 2: модификация оригинала ломает view
try {
original.add(999); // структурная модификация оригинала
sub.get(0); // ConcurrentModificationException!
} catch (ConcurrentModificationException e) {
System.out.println("View сломан: " + e);
}
// Восстановим списки для демонстрации
original = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8));
sub = original.subList(2, 5);
//Решение 1: копирование для независимой работы
List<Integer> copy = new ArrayList<>(original.subList(2, 5));
copy.set(0, 999);
copy.add(1000);
System.out.println("Original unchanged: " + original); // [1, 2, 3, 4, 5, 6, 7, 8]
System.out.println("Independent copy: " + copy); // [999, 4, 5, 1000]
//Решение 2: работа только с view без трогания оригинала
List<Integer> list = new ArrayList<>(Arrays.asList(10, 20, 30, 40, 50));
List<Integer> view = list.subList(1, 4);
// Можно безопасно читать view
System.out.println("View: " + view); // [20, 30, 40]
// Можно менять элементы через set (не структурная модификация)
view.set(1, 999);
System.out.println("Original after set: " + list); // [10, 20, 999, 40, 50]
// НО нельзя добавлять/удалять из оригинала
// list.remove(0); // сломает view!
//Альтернатива: Java 8+ Stream для создания копии
List<Integer> streamCopy = original.stream().skip(2).limit(3).collect(Collectors.toList());
System.out.println("Stream copy: " + streamCopy);
}
}Объяснение: subList() возвращает объект внутреннего класса SubList, который хранит ссылку на исходный ArrayList и смещения. Все операции делегируются исходному списку с проверкой границ. При создании SubList запоминается счетчик модификаций (modCount) оригинала. При каждой операции view сравнивает текущий modCount оригинала с запомненным. Если они различаются (оригинал был структурно изменен), выбрасывается ConcurrentModificationException.
Структурной модификацией считается изменение размера списка (add, remove, clear). Замена элементов через set() к ней не относится. Эта защита предотвращает неконсистентное состояние, когда view указывает на неправильные диапазоны.
#Java #советы
👍5
12. RabbitMQ: Полный разбор от Confirm до DLQ — всё, что нужно для надёжной очереди задач
В этом относительно коротком видео я постарался уложить теорию по RabbitMQ и короткую реализацию, которая покроет лишь минимальный сценарий.
Мы переходим от in-memory асинхронности (@Async) к настоящему брокеру сообщений — RabbitMQ.
Вы узнаете, как построить production-конвейер задач, который не теряет сообщения при падении сервиса, умеет повторять попытки, изолирует проблемные сообщения и даёт полную видимость через метрики.
Исходный код проекта на GitHub очень ждет Ваших звезд☺️ (Вам че блин, жалко?)
Ссылка на Youtube
Ссылка на Рутьюб
Смотрите, ставьте лайки, подписывайтесь на каналы!✌️
❗️ ❗️ ❗️ Огромная просьба - если Вам понравилась моя работа, распространите эту серию по всем доступным вам местам: телеграм, discord и прочим каналам. ❗️ ❗️ ❗️
Буду крайне благодарен🙂
В этом относительно коротком видео я постарался уложить теорию по RabbitMQ и короткую реализацию, которая покроет лишь минимальный сценарий.
Мы переходим от in-memory асинхронности (@Async) к настоящему брокеру сообщений — RabbitMQ.
Вы узнаете, как построить production-конвейер задач, который не теряет сообщения при падении сервиса, умеет повторять попытки, изолирует проблемные сообщения и даёт полную видимость через метрики.
Исходный код проекта на GitHub очень ждет Ваших звезд
Ссылка на Youtube
Ссылка на Рутьюб
Смотрите, ставьте лайки, подписывайтесь на каналы!
Буду крайне благодарен
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥5
Что выведет код?
#Tasks
import java.util.*;
public class Task290426 {
public static void main(String[] args) {
List<Integer> original = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
List<Integer> sub = original.subList(1, 4);
sub.add(99);
original.add(100);
System.out.println(sub.size());
System.out.println(original.size());
}
}
#Tasks
👍2
👍2
Что такое NPE (NullPointerException) и как его избежать? 🤓
Ответ:
NullPointerException — это исключение, которое возникает, когда программа пытается использовать ссылку, которая не указывает ни на какой объект (равна null).
Типичные ситуации: вызов метода у null, обращение к полю, доступ к элементу массива.
Способы избежать:
1) проверка на null перед использованием (if (obj != null)).
2) использование Optional.
3) использование Objects.requireNonNull().
4) аннотации @Nullable и @NonNull (IDE и статические анализаторы).
5) избегание возврата null (возвращайте пустую коллекцию или Optional).
#собеседование
Ответ:
Типичные ситуации: вызов метода у null, обращение к полю, доступ к элементу массива.
Способы избежать:
1) проверка на null перед использованием (if (obj != null)).
2) использование Optional.
3) использование Objects.requireNonNull().
4) аннотации
5) избегание возврата null (возвращайте пустую коллекцию или Optional).
#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
История технологии сегодня — 30 апреля
ℹ️ Кто родился в этот день
Клод Э́лвуд Ше́ннон (англ. Claude Elwood Shannon; 30 апреля 1916, Петоски, Мичиган, США — 24 февраля 2001, Медфорд, Массачусетс, США) — американский инженер, криптоаналитик и математик. Считается «отцом информационного века».
Является основателем теории информации, нашедшей применение в современных высокотехнологических системах связи. Предоставил фундаментальные понятия, идеи и их математические формулировки, которые в настоящее время формируют основу для современных коммуникационных технологий. В 1948 году предложил использовать слово «бит» для обозначения наименьшей единицы информации (в статье «Математическая теория связи»). Кроме того, понятие энтропии было важной особенностью теории Шеннона. Он продемонстрировал, что введённая им энтропия эквивалентна мере неопределённости информации в передаваемом сообщении. Статьи Шеннона «Математическая теория связи» и «Теория связи в секретных системах» считаются основополагающими для теории информации и криптографии. Клод Шеннон был одним из первых, кто подошёл к криптографии с научной точки зрения, он первым сформулировал её теоретические основы и ввёл в рассмотрение многие основные понятия. Шеннон внёс ключевой вклад в теорию вероятностных схем, теорию игр, теорию автоматов и теорию систем управления — области наук, входящие в понятие «кибернетика».
Иога́нн Карл Фри́дрих Га́усс (нем. Johann Carl Friedrich Gauß; 30 апреля 1777, Брауншвейг — 23 февраля 1855, Гёттинген) — немецкий математик, механик, физик, астроном и геодезист. Считается одним из величайших математиков всех времён, «королём математиков». С именем Гаусса связаны фундаментальные исследования почти во всех основных областях математики: в алгебре, теории чисел, дифференциальной и неевклидовой геометрии, математическом анализе, теории функций комплексного переменного, теории вероятностей, а также в аналитической и небесной механике, астрономии, физике и геодезии. «В каждой области глубина проникновения в материал, смелость мысли и значительность результата были поражающими.
🌐 Знаковые события
1897 — физик Джозеф Томсон на лекции в Королевском институте объявил об открытии электрона.
1993 — в Женеве объявлено, что технология Всемирной паутины (World Wide Web), разработанная сотрудником Европейской лаборатории физики элементарных частиц (CERN) англичанином Тимом Бернерсом-Ли, будет для всех бесплатной.
#Biography #Birth_Date #Events #30апреля
Клод Э́лвуд Ше́ннон (англ. Claude Elwood Shannon; 30 апреля 1916, Петоски, Мичиган, США — 24 февраля 2001, Медфорд, Массачусетс, США) — американский инженер, криптоаналитик и математик. Считается «отцом информационного века».
Является основателем теории информации, нашедшей применение в современных высокотехнологических системах связи. Предоставил фундаментальные понятия, идеи и их математические формулировки, которые в настоящее время формируют основу для современных коммуникационных технологий. В 1948 году предложил использовать слово «бит» для обозначения наименьшей единицы информации (в статье «Математическая теория связи»). Кроме того, понятие энтропии было важной особенностью теории Шеннона. Он продемонстрировал, что введённая им энтропия эквивалентна мере неопределённости информации в передаваемом сообщении. Статьи Шеннона «Математическая теория связи» и «Теория связи в секретных системах» считаются основополагающими для теории информации и криптографии. Клод Шеннон был одним из первых, кто подошёл к криптографии с научной точки зрения, он первым сформулировал её теоретические основы и ввёл в рассмотрение многие основные понятия. Шеннон внёс ключевой вклад в теорию вероятностных схем, теорию игр, теорию автоматов и теорию систем управления — области наук, входящие в понятие «кибернетика».
Иога́нн Карл Фри́дрих Га́усс (нем. Johann Carl Friedrich Gauß; 30 апреля 1777, Брауншвейг — 23 февраля 1855, Гёттинген) — немецкий математик, механик, физик, астроном и геодезист. Считается одним из величайших математиков всех времён, «королём математиков». С именем Гаусса связаны фундаментальные исследования почти во всех основных областях математики: в алгебре, теории чисел, дифференциальной и неевклидовой геометрии, математическом анализе, теории функций комплексного переменного, теории вероятностей, а также в аналитической и небесной механике, астрономии, физике и геодезии. «В каждой области глубина проникновения в материал, смелость мысли и значительность результата были поражающими.
1897 — физик Джозеф Томсон на лекции в Королевском институте объявил об открытии электрона.
1993 — в Женеве объявлено, что технология Всемирной паутины (World Wide Web), разработанная сотрудником Европейской лаборатории физики элементарных частиц (CERN) англичанином Тимом Бернерсом-Ли, будет для всех бесплатной.
#Biography #Birth_Date #Events #30апреля
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Forwarded from ChatRoom (Java for Beginner)
Хохма дня))) Вот что отвечает нейронка о изучении 1С 😂😂😂
🤓2
Раздел 9. Исключения, логирование, отладка
Глава 1. Иерархия исключений (Exceptions)
Objects.requireNonNull() – стандартная фабрика NullPointerException
Null-ссылка, введенная Тони Хоаром в 1965 году, впоследствии названная им "миллиардной ошибкой" (billion-dollar mistake), остается одним из наиболее частых источников runtime-ошибок в Java. NullPointerException занимает второе место по частоте среди всех дефектов программного обеспечения, что подчеркивает масштаб проблемы.
В Java nullability является неявной: если API не документировано явно, разработчик не может быть уверен, может ли возвращаемое значение быть null, что приводит к недопониманию и багам.
До Java 7 проверка параметров на null выполнялась через явные условия:
Этот подход многословен и не предоставляет стандартизированного способа валидации. Java 7 ввела класс java.util.Objects с методом requireNonNull(), который превратил проверку null в однострочную операцию с гибкими возможностями кастомизации сообщений.
Методы requireNonNull: три перегрузки
Класс Objects предоставляет три перегруженные версии requireNonNull, каждая из которых подходит для разных сценариев:
Все три версии возвращают переданный объект, если он не null, что позволяет использовать их inline при инициализации полей или передаче параметров. Если объект null, выбрасывается NullPointerException с соответствующим сообщением.
Базовая версия: fail-fast без лишних слов
Здесь requireNonNull(repository) возвращает repository, если он не null, или выбрасывает NullPointerException с дефолтным сообщением. Этот паттерн идеален для конструкторов, где требуется гарантия ненулевых зависимостей, а специфичное сообщение не критично.
Версия со статическим сообщением: контекст для отладки
Статическое сообщение предоставляет контекст при возникновении исключения, облегчая отладку. Однако сообщение вычисляется всегда, даже если объект не null, что незначительно, но избыточно для горячих путей выполнения.
Версия с Supplier: ленивое вычисление сообщений
Третья перегрузка принимает Supplier<String> и вычисляет сообщение только при фактической необходимости — когда объект равен null:
Эта версия критически важна для сценариев, где формирование сообщения требует значительных вычислений: конкатенация строк, форматирование дат, обращение к внешним ресурсам. При нормальном выполнении Supplier не вызывается, что устраняет накладные расходы.
Сравнение производительности:
В первом случае конкатенация строк выполняется при каждом вызове метода. Во втором — только при нарушении предусловия.
#Java #для_новичков #beginner #exception #requireNonNull
Глава 1. Иерархия исключений (Exceptions)
Objects.requireNonNull() – стандартная фабрика NullPointerException
Null-ссылка, введенная Тони Хоаром в 1965 году, впоследствии названная им "миллиардной ошибкой" (billion-dollar mistake), остается одним из наиболее частых источников runtime-ошибок в Java. NullPointerException занимает второе место по частоте среди всех дефектов программного обеспечения, что подчеркивает масштаб проблемы.
В Java nullability является неявной: если API не документировано явно, разработчик не может быть уверен, может ли возвращаемое значение быть null, что приводит к недопониманию и багам.
До Java 7 проверка параметров на null выполнялась через явные условия:
public void processOrder(Order order) {
if (order == null) {
throw new NullPointerException("Order cannot be null");
}
// Основная логика
}Этот подход многословен и не предоставляет стандартизированного способа валидации. Java 7 ввела класс java.util.Objects с методом requireNonNull(), который превратил проверку null в однострочную операцию с гибкими возможностями кастомизации сообщений.
Методы requireNonNull: три перегрузки
Класс Objects предоставляет три перегруженные версии requireNonNull, каждая из которых подходит для разных сценариев:
// 1. Базовая версия без сообщения
public static <T> T requireNonNull(T obj)
// 2. Версия со статическим сообщением
public static <T> T requireNonNull(T obj, String message)
// 3. Версия с ленивым сообщением через Supplier
public static <T> T requireNonNull(T obj, Supplier<String> messageSupplier)
Все три версии возвращают переданный объект, если он не null, что позволяет использовать их inline при инициализации полей или передаче параметров. Если объект null, выбрасывается NullPointerException с соответствующим сообщением.
Базовая версия: fail-fast без лишних слов
public class OrderService {
private final OrderRepository repository;
public OrderService(OrderRepository repository) {
this.repository = Objects.requireNonNull(repository);
}
}Здесь requireNonNull(repository) возвращает repository, если он не null, или выбрасывает NullPointerException с дефолтным сообщением. Этот паттерн идеален для конструкторов, где требуется гарантия ненулевых зависимостей, а специфичное сообщение не критично.
Версия со статическим сообщением: контекст для отладки
public void updateInventory(Inventory inventory, String warehouseId) {
Objects.requireNonNull(inventory, "Inventory object cannot be null");
Objects.requireNonNull(warehouseId, "Warehouse ID must be specified");
inventory.adjustStock(warehouseId);
}Статическое сообщение предоставляет контекст при возникновении исключения, облегчая отладку. Однако сообщение вычисляется всегда, даже если объект не null, что незначительно, но избыточно для горячих путей выполнения.
Версия с Supplier: ленивое вычисление сообщений
Третья перегрузка принимает Supplier<String> и вычисляет сообщение только при фактической необходимости — когда объект равен null:
public void processTransaction(Transaction tx) {
Objects.requireNonNull(tx,
() -> String.format("Transaction cannot be null at %s", Instant.now()));
// Сложное форматирование выполняется только если tx == null
}Эта версия критически важна для сценариев, где формирование сообщения требует значительных вычислений: конкатенация строк, форматирование дат, обращение к внешним ресурсам. При нормальном выполнении Supplier не вызывается, что устраняет накладные расходы.
Сравнение производительности:
// Избыточно: сообщение формируется всегда
Objects.requireNonNull(user, "User " + userId + " not found in database " + dbName);
// Эффективно: сообщение формируется только при null
Objects.requireNonNull(user,
() -> "User " + userId + " not found in database " + dbName);
В первом случае конкатенация строк выполняется при каждом вызове метода. Во втором — только при нарушении предусловия.
#Java #для_новичков #beginner #exception #requireNonNull
👍3
Когда использовать requireNonNull
Валидация параметров методов и конструкторов
Основное применение requireNonNull — проверка предусловий (preconditions) на границе метода. Это реализация принципа fail-fast: ошибка обнаруживается немедленно, предотвращая каскадные сбои и упрощая отладку. Если метод валидирует параметры upfront, он быстро завершается с четким исключением, указывающим источник проблемы.
Гарантия ненулевых возвращаемых значений
requireNonNull может использоваться для защиты от непреднамеренного возврата null из методов, особенно при делегировании к внутренним компонентам:
Здесь requireNonNull служит последней линией защиты: если репозиторий вернул null (что не должно происходить по контракту, но возможно из-за бага), метод выбросит NullPointerException с информативным сообщением вместо передачи null вызывающему коду.
Защита внутреннего состояния при делегировании
При реализации методов, делегирующих вызовы внутренним объектам, requireNonNull гарантирует, что поле инициализировано:
Вызов fetchData() до initialize() выбросит NullPointerException с понятным сообщением, вместо стандартного NPE на разыменовании null.
Документирование через Javadoc
Использование requireNonNull должно сопровождаться документированием в Javadoc. Тег @throws указывает, что метод выбрасывает NullPointerException при нарушении параметрических ограничений:
Для классов, где множество методов выбрасывают NullPointerException при нарушении предусловий, можно документировать это на уровне класса, избегая повторений в каждом методе.
Связь с аннотациями @NonNull
Разделение ответственности: runtime vs compile-time
Objects.requireNonNull() обеспечивает runtime-проверку: исключение возникает во время выполнения, если null передан в метод. Аннотации @NonNull (и их аналоги) предоставляют compile-time информацию о nullability, позволяя IDE и статическим анализаторам предупреждать о потенциальных проблемах до запуска программы.
Эти механизмы комплементарны, а не взаимоисключающие. Аннотации @NonNull документируют контракт и помогают инструментам, но не обеспечивают runtime-защиту. requireNonNull гарантирует защиту во время выполнения, но не предоставляет информации для статического анализа. Идеальный подход — комбинировать оба механизма.
#Java #для_новичков #beginner #exception #requireNonNull
Валидация параметров методов и конструкторов
Основное применение requireNonNull — проверка предусловий (preconditions) на границе метода. Это реализация принципа fail-fast: ошибка обнаруживается немедленно, предотвращая каскадные сбои и упрощая отладку. Если метод валидирует параметры upfront, он быстро завершается с четким исключением, указывающим источник проблемы.
public class PaymentProcessor {
private final PaymentGateway gateway;
private final TransactionLogger logger;
public PaymentProcessor(PaymentGateway gateway, TransactionLogger logger) {
this.gateway = Objects.requireNonNull(gateway, "PaymentGateway is required");
this.logger = Objects.requireNonNull(logger, "TransactionLogger is required");
}
public PaymentResult process(PaymentRequest request) {
Objects.requireNonNull(request, "PaymentRequest cannot be null");
gateway.authorize(request);
logger.log(request);
return new PaymentResult();
}
}Гарантия ненулевых возвращаемых значений
requireNonNull может использоваться для защиты от непреднамеренного возврата null из методов, особенно при делегировании к внутренним компонентам:
public Customer getCustomer(String customerId) {
Customer customer = customerRepository.findById(customerId);
return Objects.requireNonNull(customer,
() -> "Customer not found for ID: " + customerId);
}Здесь requireNonNull служит последней линией защиты: если репозиторий вернул null (что не должно происходить по контракту, но возможно из-за бага), метод выбросит NullPointerException с информативным сообщением вместо передачи null вызывающему коду.
Защита внутреннего состояния при делегировании
При реализации методов, делегирующих вызовы внутренним объектам, requireNonNull гарантирует, что поле инициализировано:
public class CachedDataProvider {
private DataProvider delegate;
public void initialize(DataProvider provider) {
this.delegate = Objects.requireNonNull(provider);
}
public Data fetchData() {
return Objects.requireNonNull(delegate, "Provider not initialized").fetch();
}
}Вызов fetchData() до initialize() выбросит NullPointerException с понятным сообщением, вместо стандартного NPE на разыменовании null.
Документирование через Javadoc
Использование requireNonNull должно сопровождаться документированием в Javadoc. Тег @throws указывает, что метод выбрасывает NullPointerException при нарушении параметрических ограничений:
/**
* Обрабатывает платеж через указанный шлюз.
*
* @param request запрос на платеж, не может быть null
* @param gateway платежный шлюз, не может быть null
* @return результат обработки платежа
* @throws NullPointerException если request или gateway равны null
*/
public PaymentResult process(PaymentRequest request, PaymentGateway gateway) {
Objects.requireNonNull(request, "PaymentRequest is required");
Objects.requireNonNull(gateway, "PaymentGateway is required");
return gateway.process(request);
}
Для классов, где множество методов выбрасывают NullPointerException при нарушении предусловий, можно документировать это на уровне класса, избегая повторений в каждом методе.
Связь с аннотациями @NonNull
Разделение ответственности: runtime vs compile-time
Objects.requireNonNull() обеспечивает runtime-проверку: исключение возникает во время выполнения, если null передан в метод. Аннотации @NonNull (и их аналоги) предоставляют compile-time информацию о nullability, позволяя IDE и статическим анализаторам предупреждать о потенциальных проблемах до запуска программы.
Эти механизмы комплементарны, а не взаимоисключающие. Аннотации @NonNull документируют контракт и помогают инструментам, но не обеспечивают runtime-защиту. requireNonNull гарантирует защиту во время выполнения, но не предоставляет информации для статического анализа. Идеальный подход — комбинировать оба механизма.
#Java #для_новичков #beginner #exception #requireNonNull
👍3
Экосистема аннотаций nullability
В Java-экосистеме существует множество аннотаций @NonNull из разных источников, каждая со своей семантикой и областью применения:
JSpecify (org.jspecify.annotations.NonNull) — современный стандарт, разработанный консорциумом Google, JetBrains, Spring и других. Применяется к использованию типа (type use), что позволяет различать nullability элементов массивов и generic-типов.
Spring Framework (org.springframework.lang.NonNull) — устаревшие аннотации из Spring 5, deprecated в Spring 7 в пользу JSpecify. Применялись к полям, параметрам и возвращаемым значениям.
JetBrains (org.jetbrains.annotations.NotNull) — аннотации IntelliJ IDEA, широко поддерживаемые IDE и Kotlin-компилятором.
JSR-305 (javax.annotation.Nonnull) — спецификация, больше не поддерживаемая активно, но широко распространенная в legacy-коде.
Jakarta Bean Validation (jakarta.validation.constraints.NotNull) — используется для runtime-валидации в фреймворках вроде Hibernate Validator.
JSpecify: современный стандарт
JSpecify, выпущенный в версии 1.0.0, представляет собой наиболее перспективный стандарт для null safety в Java. Он определяет три состояния nullability: unspecified (не указано), nullable (@Nullable) и non-null (@NonNull). Ключевая особенность — аннотация @NullMarked, применяемая на уровне пакета, которая устанавливает non-null как значение по умолчанию для всех типов в пакете, устраняя необходимость в явном @NonNull для каждого параметра.
После этого все параметры, возвращаемые значения и поля в пакете считаются non-null по умолчанию. Только явно аннотированные @Nullable типы могут содержать null.
Интеграция requireNonNull с аннотациями
Комбинированный подход использует @NonNull (или неявный non-null через @NullMarked) для документирования контракта и статического анализа, и requireNonNull для runtime-защиты:
В этом примере:
IDE и статические анализаторы (NullAway, Checker Framework) предупреждают о попытке передать null в non-null параметры на этапе разработки
requireNonNull гарантирует защиту во время выполнения, если статический анализ был проигнорирован или null пришел из неаннотированного кода
Кастомные сообщения в requireNonNull обеспечивают контекст при runtime-ошибках
#Java #для_новичков #beginner #exception #requireNonNull
В Java-экосистеме существует множество аннотаций @NonNull из разных источников, каждая со своей семантикой и областью применения:
JSpecify (org.jspecify.annotations.NonNull) — современный стандарт, разработанный консорциумом Google, JetBrains, Spring и других. Применяется к использованию типа (type use), что позволяет различать nullability элементов массивов и generic-типов.
Spring Framework (org.springframework.lang.NonNull) — устаревшие аннотации из Spring 5, deprecated в Spring 7 в пользу JSpecify. Применялись к полям, параметрам и возвращаемым значениям.
JetBrains (org.jetbrains.annotations.NotNull) — аннотации IntelliJ IDEA, широко поддерживаемые IDE и Kotlin-компилятором.
JSR-305 (javax.annotation.Nonnull) — спецификация, больше не поддерживаемая активно, но широко распространенная в legacy-коде.
Jakarta Bean Validation (jakarta.validation.constraints.NotNull) — используется для runtime-валидации в фреймворках вроде Hibernate Validator.
JSpecify: современный стандарт
JSpecify, выпущенный в версии 1.0.0, представляет собой наиболее перспективный стандарт для null safety в Java. Он определяет три состояния nullability: unspecified (не указано), nullable (@Nullable) и non-null (@NonNull). Ключевая особенность — аннотация @NullMarked, применяемая на уровне пакета, которая устанавливает non-null как значение по умолчанию для всех типов в пакете, устраняя необходимость в явном @NonNull для каждого параметра.
// package-info.java
@NullMarked
package com.example.service;
import org.jspecify.annotations.NullMarked;
После этого все параметры, возвращаемые значения и поля в пакете считаются non-null по умолчанию. Только явно аннотированные @Nullable типы могут содержать null.
package com.example.service;
import org.jspecify.annotations.Nullable;
public class UserService {
// Не требует @NonNull — non-null по умолчанию благодаря @NullMarked
public User findById(String id) {
// ...
}
// Явно указано, что может вернуть null
public @Nullable User findByEmail(String email) {
// ...
}
// Параметр явно nullable
public void updateNickname(String id, @Nullable String nickname) {
// ...
}
}
Интеграция requireNonNull с аннотациями
Комбинированный подход использует @NonNull (или неявный non-null через @NullMarked) для документирования контракта и статического анализа, и requireNonNull для runtime-защиты:
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
@NullMarked
public class OrderService {
private final PaymentGateway gateway;
public OrderService(PaymentGateway gateway) {
// Runtime-защита: выбросит NPE с сообщением
this.gateway = Objects.requireNonNull(gateway, "PaymentGateway is required");
}
// Метод принимает non-null по умолчанию (благодаря @NullMarked)
public Order processOrder(String orderId) {
Objects.requireNonNull(orderId, "Order ID is required");
return gateway.process(orderId);
}
// Явно nullable параметр
public Order processOrderWithNotes(String orderId, @Nullable String notes) {
Objects.requireNonNull(orderId, "Order ID is required");
// notes может быть null — допустимо по контракту
return gateway.process(orderId, notes);
}
}
В этом примере:
IDE и статические анализаторы (NullAway, Checker Framework) предупреждают о попытке передать null в non-null параметры на этапе разработки
requireNonNull гарантирует защиту во время выполнения, если статический анализ был проигнорирован или null пришел из неаннотированного кода
Кастомные сообщения в requireNonNull обеспечивают контекст при runtime-ошибках
#Java #для_новичков #beginner #exception #requireNonNull
👍3
Что выведет код?
#Tasks
import java.util.Objects;
public class Task300426 {
public static void main(String[] args) {
String s1 = null;
String s2 = "hello";
String result = Objects.requireNonNull(
Objects.requireNonNull(s1, "first is null"),
"second is null"
);
System.out.println(result);
}
}
#Tasks
👍2
👍2
Java for Beginner
12. RabbitMQ: Полный разбор от Confirm до DLQ — всё, что нужно для надёжной очереди задач В этом относительно коротком видео я постарался уложить теорию по RabbitMQ и короткую реализацию, которая покроет лишь минимальный сценарий. Мы переходим от in-memory…
Кто посмотрел, дайте обратную связь? ☺️
Есть ли проблемы?💃
Есть ли проблемы?
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥3
Что такое String.format() и System.out.printf()? 🤓
Ответ:
String.format() — статический метод, который создает отформатированную строку с использованием спецификаторов формата (например, %s для строки, %d для целых чисел, %f для дробных, %n для перевода строки).
System.out.printf() делает то же самое, но сразу выводит в консоль (аналог System.out.println(String.format(...))).
Пример: String name = "Alice"; int age = 30; String msg = String.format("Name: %s, Age: %d", name, age);.
#собеседование
Ответ:
System.out.printf() делает то же самое, но сразу выводит в консоль (аналог System.out.println(String.format(...))).
Пример: String name = "Alice"; int age = 30; String msg = String.format("Name: %s, Age: %d", name, age);.
#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
История технологии сегодня — 01 мая
ℹ️ Кто родился в этот день
Ра́дик Мартиро́сович Мартирося́н (арм. Ռադիկ Մարտիրոսի Մարտիրոսյան; 1 мая 1936, село Мадагиз, Нагорно-Карабахская АО, Азербайджанская ССР — 5 мая 2025) — советский и армянский физик, специалист по квантовой электронике, радиофизике и радиоастрономии. В Институте радиофизики и электроники АН Армянской ССР под его руководством велись фундаментальные и прикладные исследования в области высокотемпературной сверхпроводимости. Впервые обнаружено интенсивное квази-монохроматическое собственное излучение в сверхвысокочастотном диапазоне в мостиковых пленочных структурах из высокотемпературного сверхпроводника.
Пи́тер Дэ́вид Лакс (венг. Lax Péter Dávid, англ. Peter David Lax; 1 мая 1926, Будапешт, Королевство Венгрия — 16 мая 2025, Манхэттен, Нью-Йорк) — американский математик, лауреат премии Вольфа (1987) и Абелевской премии (2005). Поле деятельности Лакса многогранно: в частности, в него входило изучение интегрируемых систем, ударной волны, гидродинамики. Он также внёс существенный вклад в развитие теории солитонов. С его именем связаны такие математические достижения и числовые методы как лемма Лакса — Мильграма, теорема эквивалентности Лакса, схема Лакса — Фридрихса, схема Лакса — Вендрофа, условие энтропии Лакса и теория Лакса — Левермора, уравнение Лакса.
🌐 Знаковые события
1006 — вспыхнула сверхновая звезда SN 1006.
1930 – опубликовано имя открытой 18 февраля девятой планеты Солнечной системы — Плутон.
#Biography #Birth_Date #Events #01мая
Ра́дик Мартиро́сович Мартирося́н (арм. Ռադիկ Մարտիրոսի Մարտիրոսյան; 1 мая 1936, село Мадагиз, Нагорно-Карабахская АО, Азербайджанская ССР — 5 мая 2025) — советский и армянский физик, специалист по квантовой электронике, радиофизике и радиоастрономии. В Институте радиофизики и электроники АН Армянской ССР под его руководством велись фундаментальные и прикладные исследования в области высокотемпературной сверхпроводимости. Впервые обнаружено интенсивное квази-монохроматическое собственное излучение в сверхвысокочастотном диапазоне в мостиковых пленочных структурах из высокотемпературного сверхпроводника.
Пи́тер Дэ́вид Лакс (венг. Lax Péter Dávid, англ. Peter David Lax; 1 мая 1926, Будапешт, Королевство Венгрия — 16 мая 2025, Манхэттен, Нью-Йорк) — американский математик, лауреат премии Вольфа (1987) и Абелевской премии (2005). Поле деятельности Лакса многогранно: в частности, в него входило изучение интегрируемых систем, ударной волны, гидродинамики. Он также внёс существенный вклад в развитие теории солитонов. С его именем связаны такие математические достижения и числовые методы как лемма Лакса — Мильграма, теорема эквивалентности Лакса, схема Лакса — Фридрихса, схема Лакса — Вендрофа, условие энтропии Лакса и теория Лакса — Левермора, уравнение Лакса.
1006 — вспыхнула сверхновая звезда SN 1006.
1930 – опубликовано имя открытой 18 февраля девятой планеты Солнечной системы — Плутон.
#Biography #Birth_Date #Events #01мая
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
[Совет по Java #032]
Тема: Arrays.asList() возвращает список фиксированного размера.
Проблема: Метод Arrays.asList(T... a) возвращает не java.util.ArrayList, а внутренний статический класс Arrays.ArrayList, который не реализует операции изменения размера.
Этот список является представлением (view) переданного массива. Попытка вызвать add(), remove(), clear() или другие методы, изменяющие размер, выбрасывает UnsupportedOperationException. Даже метод clear(), который кажется безопасным, выбрасывает исключение.
Решение: Если нужен изменяемый список, создайте новый ArrayList на основе результата Arrays.asList(): new ArrayList<>(Arrays.asList(с)).
Начиная с Java 9, можно использовать List.of() для неизменяемых списков (еще более строгие ограничения) или List.copyOf(). Если массив уже существует, и нужно его изменяемое представление, используйте цикл или Stream API. Помните, что изменения существующих элементов через set() работают и отражаются на исходном массиве.
Объяснение: Arrays.asList() предназначен для быстрого создания оболочки вокруг массива для использования в API, требующих Collection. Возвращаемый объект хранит ссылку на исходный массив и не поддерживает изменение размера, так как массив имеет фиксированную длину. Методы add, remove, clear не переопределены и наследуются от AbstractList, где по умолчанию выбрасывают UnsupportedOperationException.
При этом метод set() переопределен и работает корректно, изменяя соответствующий элемент в массиве. Важно помнить, что изменения в списке видны в исходном массиве, и наоборот. Начиная с Java 8, для примитивных массивов удобнее использовать стримы с boxed(). Java 9 ввел List.of(), который создает полностью неизменяемые списки (даже set() не работает), что лучше для констант.
#Java #советы
Тема: Arrays.asList() возвращает список фиксированного размера.
Проблема: Метод Arrays.asList(T... a) возвращает не java.util.ArrayList, а внутренний статический класс Arrays.ArrayList, который не реализует операции изменения размера.
Этот список является представлением (view) переданного массива. Попытка вызвать add(), remove(), clear() или другие методы, изменяющие размер, выбрасывает UnsupportedOperationException. Даже метод clear(), который кажется безопасным, выбрасывает исключение.
Решение: Если нужен изменяемый список, создайте новый ArrayList на основе результата Arrays.asList(): new ArrayList<>(Arrays.asList(с)).
Начиная с Java 9, можно использовать List.of() для неизменяемых списков (еще более строгие ограничения) или List.copyOf(). Если массив уже существует, и нужно его изменяемое представление, используйте цикл или Stream API. Помните, что изменения существующих элементов через set() работают и отражаются на исходном массиве.
public class ArraysAsListExample {
public static void main(String[] args) {
String[] colorsArray = {"Red", "Green", "Blue"};
//Антипаттерн: модификация списка из Arrays.asList()
List<String> fixedList = Arrays.asList(colorsArray);
System.out.println("Fixed list: " + fixedList); // [Red, Green, Blue]
try {
fixedList.add("Yellow"); // UnsupportedOperationException
} catch (UnsupportedOperationException e) {
System.out.println("Cannot add: " + e);
}
try {
fixedList.remove(0); // UnsupportedOperationException
} catch (UnsupportedOperationException e) {
System.out.println("Cannot remove: " + e);
}
try {
fixedList.clear(); // Тоже UnsupportedOperationException
} catch (UnsupportedOperationException e) {
System.out.println("Cannot clear: " + e);
}
//Можно изменять существующие элементы
fixedList.set(0, "Cyan");
System.out.println("After set: " + fixedList); // [Cyan, Green, Blue]
// Обратите внимание: исходный массив тоже изменился!
System.out.println("Original array: " + Arrays.toString(colorsArray)); // [Cyan, Green, Blue]
//Решение 1: копирование в новый ArrayList
List<String> mutableList = new ArrayList<>(Arrays.asList(colorsArray));
mutableList.add("Yellow");
mutableList.remove(0);
System.out.println("Mutable list: " + mutableList);
//Решение 2: Java 8+ Stream для примитивов
List<Integer> numbers = Arrays.stream(new int[]{1, 2, 3})
.boxed()
.collect(Collectors.toList());
numbers.add(4);
System.out.println("From stream: " + numbers);
//Решение 3: Java 9+ неизменяемые списки
List<String> immutable = List.of("A", "B", "C");
// immutable.add("D"); // UnsupportedOperationException
// immutable.set(0, "Z"); // Также выбрасывает исключение!
//Решение 4: явное создание ArrayList с инициализацией
List<String> explicit = new ArrayList<>();
explicit.add("X");
explicit.add("Y");
explicit.add("Z");
}Объяснение: Arrays.asList() предназначен для быстрого создания оболочки вокруг массива для использования в API, требующих Collection. Возвращаемый объект хранит ссылку на исходный массив и не поддерживает изменение размера, так как массив имеет фиксированную длину. Методы add, remove, clear не переопределены и наследуются от AbstractList, где по умолчанию выбрасывают UnsupportedOperationException.
При этом метод set() переопределен и работает корректно, изменяя соответствующий элемент в массиве. Важно помнить, что изменения в списке видны в исходном массиве, и наоборот. Начиная с Java 8, для примитивных массивов удобнее использовать стримы с boxed(). Java 9 ввел List.of(), который создает полностью неизменяемые списки (даже set() не работает), что лучше для констант.
#Java #советы
👍6
Что выведет код?
#Tasks
import java.util.Arrays;
import java.util.List;
public class Task010526 {
public static void main(String[] args) {
List<String> list = Arrays.asList("A", "B", "C");
String[] array = {"X", "Y", "Z"};
List<String> list2 = Arrays.asList(array);
list.set(1, "B2");
array[2] = "Z2";
System.out.print(list.get(1) + " ");
System.out.print(list2.get(2) + " ");
try {
list.add("D");
} catch (Exception e) {
System.out.print("Exception1 ");
}
try {
list2.remove(0);
} catch (Exception e) {
System.out.print("Exception2");
}
}
}
#Tasks
👍2
Варианты ответа:
Anonymous Quiz
18%
B2 Z2
18%
B2 Z2 Exception1
55%
B2 Z2 Exception1 Exception2
9%
B Z2 Exception1 Exception2
👍1🔥1
Что такое Date и Calendar? Какие есть альтернативы? 🤓
Ответ:
java.util.Date — представляет момент времени (миллисекунды с 1970-01-01). Многие методы устарели.
java.util.Calendar — абстрактный класс для работы с датами и временем (получение компонентов: год, месяц, день и т.д.).
Оба имеют проблемы: мутабельность, неинтуитивные индексы месяцев (0-11), неудобство.
Начиная с Java 8, появился новый пакет java.time (LocalDate, LocalTime, LocalDateTime, ZonedDateTime, Duration, Period) — immutable, потокобезопасный, интуитивный.
#собеседование
Ответ:
java.util.Calendar — абстрактный класс для работы с датами и временем (получение компонентов: год, месяц, день и т.д.).
Оба имеют проблемы: мутабельность, неинтуитивные индексы месяцев (0-11), неудобство.
Начиная с Java 8, появился новый пакет java.time (LocalDate, LocalTime, LocalDateTime, ZonedDateTime, Duration, Period) — immutable, потокобезопасный, интуитивный.
#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
Всем привет! ✌️
Так как неожиданно для меня самого у меня стало много свободного времени, наберу желающих изучить Java.
Золотых гор не обещаю, но на Junior+/ middle вытяну однозначно.
Моя экспертиза по видео и каналу, наверняка понятна.
Пишите в лс @Oleborn
Так как неожиданно для меня самого у меня стало много свободного времени, наберу желающих изучить Java.
Золотых гор не обещаю, но на Junior+/ middle вытяну однозначно.
Моя экспертиза по видео и каналу, наверняка понятна.
Пишите в лс @Oleborn
🔥7👍1
История технологии сегодня — 02 мая
ℹ️ Кто родился в этот день
Сю Такуми (яп. 巧 舟 Такуми Сю:) (род. май 1971, Сайтама) — японский сценарист и геймдизайнер. Наиболее известен своей работой над серией игр Ace Attorney. Также он был сценаристом игры Ghost Trick: Phantom Detective, вышедшей в 2010 году.
🌐 Знаковые события
Не нашел((
#Biography #Birth_Date #Events #02мая
Сю Такуми (яп. 巧 舟 Такуми Сю:) (род. май 1971, Сайтама) — японский сценарист и геймдизайнер. Наиболее известен своей работой над серией игр Ace Attorney. Также он был сценаристом игры Ghost Trick: Phantom Detective, вышедшей в 2010 году.
Не нашел((
#Biography #Birth_Date #Events #02мая
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4