История технологии сегодня — 25 апреля
ℹ️ Кто родился в этот день
Андре́й Никола́евич Колмого́ров (12 (25) апреля 1903, Тамбов — 20 октября 1987, Москва) — советский математик, один из крупнейших математиков XX века. Один из основоположников современной теории вероятностей, им получены фундаментальные результаты в топологии, геометрии, математической логике, классической механике, теории турбулентности, теории сложности алгоритмов, теории информации, теории функций, теории тригонометрических рядов, теории меры, теории приближения функций, теории множеств, теории дифференциальных уравнений, теории динамических систем, функциональном анализе и в ряде других областей математики и её приложений. Автор новаторских работ по философии, истории, методологии и преподаванию математики, известны его работы в статистической физике (в частности, уравнение Джонсона — Мела — Аврами — Колмогорова).
Гулье́льмо Джова́нни Мари́я Марко́ни (итал. Guglielmo Giovanni Maria Marconi; 25 апреля 1874, Болонья — 20 июля 1937, Рим) — итальянский радиотехник, предприниматель и дипломат. Лауреат Нобелевской премии по физике за 1909 год совместно с Карлом Фердинандом Брауном «в знак признания их вклада в развитие беспроволочной телеграфии». Основатель Wireless Telegraph & Signal Company (впоследствии Marconi Company[англ.]). С именем Маркони во многих странах связывают начало практического применения радиосвязи.
🌐 Знаковые события
1826 — в Англии запатентован первый автомобиль с двигателем внутреннего сгорания.
1954 — американский исследовательский центр компании «Белл телефон» объявил о создании солнечных батарей.
2022 — Илон Маск купил «Твиттер» за 44 млрд долларов.
#Biography #Birth_Date #Events #25апреля
Андре́й Никола́евич Колмого́ров (12 (25) апреля 1903, Тамбов — 20 октября 1987, Москва) — советский математик, один из крупнейших математиков XX века. Один из основоположников современной теории вероятностей, им получены фундаментальные результаты в топологии, геометрии, математической логике, классической механике, теории турбулентности, теории сложности алгоритмов, теории информации, теории функций, теории тригонометрических рядов, теории меры, теории приближения функций, теории множеств, теории дифференциальных уравнений, теории динамических систем, функциональном анализе и в ряде других областей математики и её приложений. Автор новаторских работ по философии, истории, методологии и преподаванию математики, известны его работы в статистической физике (в частности, уравнение Джонсона — Мела — Аврами — Колмогорова).
Гулье́льмо Джова́нни Мари́я Марко́ни (итал. Guglielmo Giovanni Maria Marconi; 25 апреля 1874, Болонья — 20 июля 1937, Рим) — итальянский радиотехник, предприниматель и дипломат. Лауреат Нобелевской премии по физике за 1909 год совместно с Карлом Фердинандом Брауном «в знак признания их вклада в развитие беспроволочной телеграфии». Основатель Wireless Telegraph & Signal Company (впоследствии Marconi Company[англ.]). С именем Маркони во многих странах связывают начало практического применения радиосвязи.
1826 — в Англии запатентован первый автомобиль с двигателем внутреннего сгорания.
1954 — американский исследовательский центр компании «Белл телефон» объявил о создании солнечных батарей.
2022 — Илон Маск купил «Твиттер» за 44 млрд долларов.
#Biography #Birth_Date #Events #25апреля
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
С 18.04 по 24.04
Предыдущий пост(с 11.04 по 17.04)
Запись встреч/видео:
11. Fallback и graceful degradation — когда всё сломалось, но пользователь этого не заметил
Обучающие статьи:
Раздел 9. Исключения, логирование, отладка
Глава 1. Иерархия исключений (Exceptions)
throws в сигнатуре метода – проброс исключений наверх. Когда это оправдано
Создание своих исключений: наследование от Exception или RuntimeException. Когда кастомное исключение оправдано
Несколько ресурсов в try-with-resources: порядок закрытия и effectively final переменные (Java 9+)
[Совет по Java #028]
Тема: static-методы не переопределяются.
[Совет по Java #029]
Тема: Class.forName() загружает класс и инициализирует статические блоки.
Полезные статьи и видео:
Circuit Breaker в микросервисах: как защитить систему от каскадных отказов
Как и всегда, задачи можно найти под тегом - #Tasks, вопросы с собеседований - #собеседование
Предыдущий пост(с 11.04 по 17.04)
Запись встреч/видео:
11. Fallback и graceful degradation — когда всё сломалось, но пользователь этого не заметил
Обучающие статьи:
Раздел 9. Исключения, логирование, отладка
Глава 1. Иерархия исключений (Exceptions)
throws в сигнатуре метода – проброс исключений наверх. Когда это оправдано
Создание своих исключений: наследование от Exception или RuntimeException. Когда кастомное исключение оправдано
Несколько ресурсов в try-with-resources: порядок закрытия и effectively final переменные (Java 9+)
[Совет по Java #028]
Тема: static-методы не переопределяются.
[Совет по Java #029]
Тема: Class.forName() загружает класс и инициализирует статические блоки.
Полезные статьи и видео:
Circuit Breaker в микросервисах: как защитить систему от каскадных отказов
Как и всегда, задачи можно найти под тегом - #Tasks, вопросы с собеседований - #собеседование
👍3🔥1
Вакансия.
Я вот чего-то в этой жизни не понимаю.
Как у джуна может быть 2-3 года опыта с высоконагруженными приложениями?
Kafka/RabbitMQ....
предстоит заниматься: Проводить перекрестный в code review; - это издёвка такая? Как джун может проводить перекрестное code review?
"ЧТО У ВАС ТУТ ПРОИСХОДИТ ?!" - спрашиваю как герой смешного мема.
Но мне бл не смешно как то.
Я по приколу откликнулся - уверен что получу ботовский отказ))))
Я вот чего-то в этой жизни не понимаю.
Как у джуна может быть 2-3 года опыта с высоконагруженными приложениями?
Kafka/RabbitMQ....
предстоит заниматься: Проводить перекрестный в code review; - это издёвка такая? Как джун может проводить перекрестное code review?
"ЧТО У ВАС ТУТ ПРОИСХОДИТ ?!" - спрашиваю как герой смешного мема.
Но мне бл не смешно как то.
Я по приколу откликнулся - уверен что получу ботовский отказ))))
😱8
This media is not supported in your browser
VIEW IN TELEGRAM
Вот оно будущее...☺️
Please open Telegram to view this post
VIEW IN TELEGRAM
😱2
История технологии сегодня — 26 апреля
ℹ️ Кто родился в этот день
Арно Аллан Пе́нзиас (англ. Arno Allan Penzias; 26 апреля 1933, Мюнхен — 22 января 2024, Сан-Франциско) — американский астрофизик, профессор, лауреат Нобелевской премии по физике (1978) за открытие космического микроволнового фонового излучения. Построив приёмник, способный детектировать излучение с длиной волны порядка миллиметра и присоединив его к 36-футовому радиотелескопу, Пензиас и Вильсон обнаружили в 1970 году спектральную линию окиси углерода в области туманности Ориона, а затем ещё шесть межзвёздных молекул. Открытие и исследование межзвёздных молекулярных облаков способствовало прогрессу в понимании образования и эволюции звёзд и галактик.
🌐 Знаковые события
1986 — авария на Чернобыльской АЭС, одна из крупнейших техногенных катастроф в истории человечества.
1994 — американские учёные из Национальной лаборатории им. Ферми представили доказательства того, что ими обнаружен последний, шестой кварк (Top или t-кварк), поиск которого вёлся в течение 20 лет.
1999 — компьютерный вирус «Чернобыль» поразил, по разным оценкам, до полумиллиона компьютеров по всему миру.
#Biography #Birth_Date #Events #26апреля
Арно Аллан Пе́нзиас (англ. Arno Allan Penzias; 26 апреля 1933, Мюнхен — 22 января 2024, Сан-Франциско) — американский астрофизик, профессор, лауреат Нобелевской премии по физике (1978) за открытие космического микроволнового фонового излучения. Построив приёмник, способный детектировать излучение с длиной волны порядка миллиметра и присоединив его к 36-футовому радиотелескопу, Пензиас и Вильсон обнаружили в 1970 году спектральную линию окиси углерода в области туманности Ориона, а затем ещё шесть межзвёздных молекул. Открытие и исследование межзвёздных молекулярных облаков способствовало прогрессу в понимании образования и эволюции звёзд и галактик.
1986 — авария на Чернобыльской АЭС, одна из крупнейших техногенных катастроф в истории человечества.
1994 — американские учёные из Национальной лаборатории им. Ферми представили доказательства того, что ими обнаружен последний, шестой кварк (Top или t-кварк), поиск которого вёлся в течение 20 лет.
1999 — компьютерный вирус «Чернобыль» поразил, по разным оценкам, до полумиллиона компьютеров по всему миру.
#Biography #Birth_Date #Events #26апреля
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
This media is not supported in your browser
VIEW IN TELEGRAM
Ребят, у меня к вам вопрос - что еще реализовать на нашем сайте devforge.ru, чтобы Вам хотелось постоянно им пользоваться?
Общение? Обучающий курс? Кладовка с мемами?
Пишите, не стесняйтесь, давайте обсудим?
Общение? Обучающий курс? Кладовка с мемами?
Пишите, не стесняйтесь, давайте обсудим?
👍4
История технологии сегодня — 27 апреля
ℹ️ Кто родился в этот день
Сэ́мюэл Фи́нли Бриз Мо́рзе (англ. Samuel Finley Breese Morse [mɔːrs]; 27 апреля 1791, Чарльзтаун в штате Массачусетс — 2 апреля 1872, Нью-Йорк) — американский изобретатель и художник. Наиболее известные изобретения — электромагнитный пишущий телеграф («аппарат Морзе», 1836) и код (азбука) Морзе.
Филип Хауге Абельсон (27 апреля 1913 — 1 августа 2004) — американский физик , научный редактор и научный писатель . Получив образование в области ядерной физики , он стал одним из первооткрывателей элемента нептуния , работал над разделением изотопов в рамках Манхэттенского проекта и написал первое исследование ядерных морских двигателей для подводных лодок.
Фрэнк Уильям Абагнейл-младший ( / ˈ æ b ə ɡ n eɪ l / ; родился 27 апреля 1948 г.) — американо-французский консультант по безопасности, писатель и осужденный преступник, чьи задокументированные преступления в основном заключаются в мошенничестве с чеками и мелком воровстве, направленном против частных лиц и малых предприятий.
Начиная с конца 1970-х годов, Абагнейл утверждал, что его криминальное прошлое было гораздо более драматичным, включая длительные выдачи себя за пилота Pan American World Airways, врача больницы в Джорджии и помощника генерального прокурора Луизианы, среди прочих ролей. Эти утверждения легли в основу его автобиографии 1980 года «Поймай меня, если сможешь», написанной в соавторстве со Стэном Реддингом. Книга вдохновила на создание одноименного фильма, снятого Стивеном Спилбергом в 2002 году, в котором Абагнейла сыграл Леонардо Ди Каприо.
//Мне просто фильм нравится)
🌐 Знаковые события
2005 — первый полёт совершил авиалайнер Airbus А380.
#Biography #Birth_Date #Events #27апреля
Сэ́мюэл Фи́нли Бриз Мо́рзе (англ. Samuel Finley Breese Morse [mɔːrs]; 27 апреля 1791, Чарльзтаун в штате Массачусетс — 2 апреля 1872, Нью-Йорк) — американский изобретатель и художник. Наиболее известные изобретения — электромагнитный пишущий телеграф («аппарат Морзе», 1836) и код (азбука) Морзе.
Филип Хауге Абельсон (27 апреля 1913 — 1 августа 2004) — американский физик , научный редактор и научный писатель . Получив образование в области ядерной физики , он стал одним из первооткрывателей элемента нептуния , работал над разделением изотопов в рамках Манхэттенского проекта и написал первое исследование ядерных морских двигателей для подводных лодок.
Фрэнк Уильям Абагнейл-младший ( / ˈ æ b ə ɡ n eɪ l / ; родился 27 апреля 1948 г.) — американо-французский консультант по безопасности, писатель и осужденный преступник, чьи задокументированные преступления в основном заключаются в мошенничестве с чеками и мелком воровстве, направленном против частных лиц и малых предприятий.
Начиная с конца 1970-х годов, Абагнейл утверждал, что его криминальное прошлое было гораздо более драматичным, включая длительные выдачи себя за пилота Pan American World Airways, врача больницы в Джорджии и помощника генерального прокурора Луизианы, среди прочих ролей. Эти утверждения легли в основу его автобиографии 1980 года «Поймай меня, если сможешь», написанной в соавторстве со Стэном Реддингом. Книга вдохновила на создание одноименного фильма, снятого Стивеном Спилбергом в 2002 году, в котором Абагнейла сыграл Леонардо Ди Каприо.
//Мне просто фильм нравится)
2005 — первый полёт совершил авиалайнер Airbus А380.
#Biography #Birth_Date #Events #27апреля
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
[Совет по Java #030]
Тема: try-with-resources закрывает ресурсы в обратном порядке объявления.
Проблема: Конструкция try-with-resources автоматически закрывает ресурсы в порядке, обратном их объявлению.
Если ресурсы имеют зависимости (например, один ресурс создан на основе другого), закрытие в неправильном порядке может привести к исключениям или некорректному состоянию.
Классический пример: PrintWriter оборачивает FileOutputStream — если сначала закрыть FileOutputStream, то PrintWriter не сможет сбросить буфер при своем закрытии, и данные будут потеряны.
Решение: Всегда объявляйте ресурсы в порядке их создания (от внешнего к внутреннему). try-with-resources сам гарантирует корректный порядок закрытия: последний объявленный ресурс будет закрыт первым. Если ресурсы не зависят друг от друга, порядок не критичен, но хорошей практикой является объявление их в логическом порядке. Для сложных сценариев используйте вложенные try-with-resources или ручное управление.
Объяснение: try-with-resources генерирует код, который закрывает ресурсы в обратном порядке объявления.
Это соответствует принципу "последний пришел — первый ушел" (LIFO). Для вложенных ресурсов (когда один оборачивает другой) правильный порядок закрытия — сначала обертка, затем базовый ресурс, чтобы дать обертке возможность сбросить буферы или выполнить финальные операции.
#Java #советы
Тема: try-with-resources закрывает ресурсы в обратном порядке объявления.
Проблема: Конструкция try-with-resources автоматически закрывает ресурсы в порядке, обратном их объявлению.
Если ресурсы имеют зависимости (например, один ресурс создан на основе другого), закрытие в неправильном порядке может привести к исключениям или некорректному состоянию.
Классический пример: PrintWriter оборачивает FileOutputStream — если сначала закрыть FileOutputStream, то PrintWriter не сможет сбросить буфер при своем закрытии, и данные будут потеряны.
Решение: Всегда объявляйте ресурсы в порядке их создания (от внешнего к внутреннему). try-with-resources сам гарантирует корректный порядок закрытия: последний объявленный ресурс будет закрыт первым. Если ресурсы не зависят друг от друга, порядок не критичен, но хорошей практикой является объявление их в логическом порядке. Для сложных сценариев используйте вложенные try-with-resources или ручное управление.
public class TryWithResourcesOrder {
//Антипаттерн: ресурсы объявлены в неправильном порядке
public static void badOrder() throws IOException {
// Сначала создается FileOutputStream, потом BufferedOutputStream
// Но объявлены наоборот!
try (BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream("file.txt"));
FileOutputStream fos = new FileOutputStream("file.txt")) {
// Ошибка: FileOutputStream будет закрыт ПОСЛЕ BufferedOutputStream?
// Нет, порядок закрытия: fos -> bos (обратный объявлению)
// Но bos обертывает fos — проблема!
bos.write("Hello".getBytes());
} // При закрытии bos попытается сбросить буфер в уже закрытый fos
}
//Правильно: порядок объявления соответствует вложению
public static void goodOrder() throws IOException {
// Внешний ресурс объявлен первым, внутренний — последним
try (FileOutputStream fos = new FileOutputStream("file.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos);
PrintWriter writer = new PrintWriter(bos)) {
writer.println("Hello, World!");
writer.flush();
// Порядок закрытия: writer -> bos -> fos (обратный объявлению)
// Корректно: сначала буферы сбрасываются, потом закрываются потоки
}
}
// Демонстрация порядка закрытия
static class ResourceA implements AutoCloseable {
ResourceA() { System.out.println("ResourceA created"); }
@Override public void close() { System.out.println("ResourceA closed"); }
}
static class ResourceB implements AutoCloseable {
private final ResourceA dependsOn;
ResourceB(ResourceA a) {
this.dependsOn = a;
System.out.println("ResourceB created (depends on A)");
}
@Override public void close() {
System.out.println("ResourceB closed (using A)");
}
}
public static void demonstrateOrder() {
try (ResourceA a = new ResourceA();
ResourceB b = new ResourceB(a)) {
System.out.println("Inside try block");
}
// Вывод:
// ResourceA created
// ResourceB created (depends on A)
// Inside try block
// ResourceB closed (using A)
// ResourceA closed
// B закрывается первым, хотя может зависеть от A — это безопасно
}
public static void main(String[] args) throws Exception {
demonstrateOrder();
goodOrder();
jdbcExample();
}
}Объяснение: try-with-resources генерирует код, который закрывает ресурсы в обратном порядке объявления.
Это соответствует принципу "последний пришел — первый ушел" (LIFO). Для вложенных ресурсов (когда один оборачивает другой) правильный порядок закрытия — сначала обертка, затем базовый ресурс, чтобы дать обертке возможность сбросить буферы или выполнить финальные операции.
#Java #советы
👍5
Что выведет код?
#Tasks
public class Task270426 {
static class ResourceA270426 implements AutoCloseable {
void use() { System.out.print("A"); }
public void close() { System.out.print("closeA"); }
}
static class ResourceB270426 implements AutoCloseable {
ResourceB270426(ResourceA270426 a) { a.use(); }
public void close() { System.out.print("closeB"); }
}
public static void main(String[] args) {
try (ResourceA270426 a = new ResourceA270426();
ResourceB270426 b = new ResourceB270426(a)) {
System.out.print("use");
}
}
}#Tasks
👍2
Варианты ответа:
Anonymous Quiz
33%
AusecloseAcloseB
50%
useAcloseBcloseA
0%
AusecloseBcloseA
17%
useAcloseAcloseB
👍2
Что такое package в Java? Зачем они нужны? 🤓
Ответ:
package — это механизм группировки классов и интерфейсов.
Назначение:
1) избежание конфликтов имен (классы с одинаковым именем могут существовать в разных пакетах).
2) управление доступом (модификатор default виден внутри пакета).
3) логическая структуризация проекта. Соглашение об именах: используется перевернутое доменное имя компании (например, com.company.project.module).
Физически пакет соответствует структуре директорий.
#собеседование
Ответ:
Назначение:
1) избежание конфликтов имен (классы с одинаковым именем могут существовать в разных пакетах).
2) управление доступом (модификатор default виден внутри пакета).
3) логическая структуризация проекта. Соглашение об именах: используется перевернутое доменное имя компании (например, com.company.project.module).
Физически пакет соответствует структуре директорий.
#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
История технологии сегодня — 28 апреля
ℹ️ Кто родился в этот день
Дми́трий Бори́сович Зими́н (28 апреля 1933, Москва, РСФСР, СССР — 22 декабря 2021, Швейцария) — российский предприниматель, основатель и почётный президент компании «Вымпел-Коммуникации» (торговая марка — «Билайн»), учёный-радиотехник, доктор технических наук.
И́ан Э́шли Мёрдок (англ. Ian Ashley Murdock; 28 апреля 1973, Констанц — 28 декабря 2015, Сан-Франциско, Калифорния) — основатель проекта Debian и коммерческого дистрибутива Progeny Debian.
Курт Фри́дрих Гёдель (нем. Kurt Friedrich Gödel; 28 апреля 1906, Брюнн, Австро-Венгрия — 14 января 1978, Принстон, Нью-Джерси) — австрийский логик, математик и философ математики. Наиболее известен сформулированными и доказанными им теоремами о неполноте, которые оказали огромное влияние на представление об основаниях математики. Считается одним из наиболее выдающихся мыслителей XX века.
Никола́й Алекса́ндрович А́стров (1906—1992) — советский инженер-конструктор бронетехники. На военной службе с 1945 года. Герой Социалистического Труда (1976). До ухода на пенсию в 1985 году в должности главного конструктора ММЗ возглавлял разработку авиадесантных самоходных установок АСУ-57 и АСУ-85, самоходной установки ЗСУ-23-4 зенитного артиллерийского комплекса «Шилка», артиллерийского тягача АТП, шасси под зенитные ракетные комплексы «Куб», «Бук», «Тор» и «Тунгуска».
Ферру́ччо Ламборги́ни (итал. Ferruccio Lamborghini; 28 апреля 1916 года, Ченто, Феррара, Италия — 20 февраля 1993 года, Перуджа, Италия) — итальянский промышленник и бизнесмен, основатель Lamborghini Trattori, Automobili Lamborghini и ещё ряда компаний.
🌐 Знаковые события
2001 — полёт первого космического туриста — американца Денниса Тито.
#Biography #Birth_Date #Events #28апреля
Дми́трий Бори́сович Зими́н (28 апреля 1933, Москва, РСФСР, СССР — 22 декабря 2021, Швейцария) — российский предприниматель, основатель и почётный президент компании «Вымпел-Коммуникации» (торговая марка — «Билайн»), учёный-радиотехник, доктор технических наук.
И́ан Э́шли Мёрдок (англ. Ian Ashley Murdock; 28 апреля 1973, Констанц — 28 декабря 2015, Сан-Франциско, Калифорния) — основатель проекта Debian и коммерческого дистрибутива Progeny Debian.
Курт Фри́дрих Гёдель (нем. Kurt Friedrich Gödel; 28 апреля 1906, Брюнн, Австро-Венгрия — 14 января 1978, Принстон, Нью-Джерси) — австрийский логик, математик и философ математики. Наиболее известен сформулированными и доказанными им теоремами о неполноте, которые оказали огромное влияние на представление об основаниях математики. Считается одним из наиболее выдающихся мыслителей XX века.
Никола́й Алекса́ндрович А́стров (1906—1992) — советский инженер-конструктор бронетехники. На военной службе с 1945 года. Герой Социалистического Труда (1976). До ухода на пенсию в 1985 году в должности главного конструктора ММЗ возглавлял разработку авиадесантных самоходных установок АСУ-57 и АСУ-85, самоходной установки ЗСУ-23-4 зенитного артиллерийского комплекса «Шилка», артиллерийского тягача АТП, шасси под зенитные ракетные комплексы «Куб», «Бук», «Тор» и «Тунгуска».
Ферру́ччо Ламборги́ни (итал. Ferruccio Lamborghini; 28 апреля 1916 года, Ченто, Феррара, Италия — 20 февраля 1993 года, Перуджа, Италия) — итальянский промышленник и бизнесмен, основатель Lamborghini Trattori, Automobili Lamborghini и ещё ряда компаний.
2001 — полёт первого космического туриста — американца Денниса Тито.
#Biography #Birth_Date #Events #28апреля
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Раздел 9. Исключения, логирование, отладка
Глава 1. Иерархия исключений (Exceptions)
Исключения в лямбдах, Stream API, конструкторах и статических блоках
Java предоставляет единый механизм исключений на базе класса Throwable, но поведение этого механизма существенно различается в зависимости от контекста выполнения. Лямбда-выражения и Stream API, появившиеся в Java 8, наложили архитектурные ограничения на использование checked-исключений, требуя от разработчиков поиска обходных стратегий. Конструкторы и статические блоки инициализации представляют собой особые точки жизненного цикла класса, где исключения ведут себя нестандартно и требуют специфического подхода к управлению ресурсами и обработке ошибок.
Часть первая. Исключения в лямбдах и Stream API
Функциональные интерфейсы Java 8 — Function<T,R>, Consumer<T>, Supplier<T>, Predicate<T> и другие — объявляют свои абстрактные методы без throws. Это означает, что любой метод, выбрасывающий checked-исключение, не может быть использован напрямую как лямбда-выражение или method reference в контексте Stream API.
Это ограничение не является oversight в дизайне языка, а отражает фундаментальную несовместимость checked-исключений с функциональным программированием. В функциональном стиле функции рассматриваются как значения, которые можно передавать, комбинировать и композировать. Checked-исключения нарушают эту композицию, требуя явной обработки на каждом уровне трансформации.
Стратегия первая: обёртка в try-catch внутри лямбды
Наиболее прямолинейный подход — обернуть вызов метода с checked-исключением в try-catch блок внутри лямбды и транслировать checked в unchecked:
Этот подход работает, но имеет серьезные недостатки. Во-первых, он загромождает код шаблонной обработкой исключений, разрушая лаконичность функционального стиля. Во-вторых, выброс RuntimeException из лямбды в Stream API прерывает весь конвейер — невозможно обработать ошибку для одного элемента и продолжить обработку остальных. В-третьих, исключение теряет семантику checked, и вызывающий код может не осознавать возможность сбоя.
Для сценариев, где требуется игнорировать ошибки и продолжить обработку, можно возвращать значение по умолчанию:
Здесь NumberFormatException — unchecked-исключение, но паттерн применим и к checked. Фильтрация Objects::nonNull удаляет null-значения, соответствующие ошибкам парсинга. Однако этот подход имеет побочный эффект: информация об ошибках теряется без логирования.
Улучшенная версия с логированием:
#Java #для_новичков #beginner #exception
Глава 1. Иерархия исключений (Exceptions)
Исключения в лямбдах, Stream API, конструкторах и статических блоках
Java предоставляет единый механизм исключений на базе класса Throwable, но поведение этого механизма существенно различается в зависимости от контекста выполнения. Лямбда-выражения и Stream API, появившиеся в Java 8, наложили архитектурные ограничения на использование checked-исключений, требуя от разработчиков поиска обходных стратегий. Конструкторы и статические блоки инициализации представляют собой особые точки жизненного цикла класса, где исключения ведут себя нестандартно и требуют специфического подхода к управлению ресурсами и обработке ошибок.
Часть первая. Исключения в лямбдах и Stream API
Функциональные интерфейсы Java 8 — Function<T,R>, Consumer<T>, Supplier<T>, Predicate<T> и другие — объявляют свои абстрактные методы без throws. Это означает, что любой метод, выбрасывающий checked-исключение, не может быть использован напрямую как лямбда-выражение или method reference в контексте Stream API.
// Метод с checked-исключением
public String fetchUrl(String url) throws IOException {
return httpClient.fetch(url);
}
// Ошибка компиляции: unreported exception IOException
List<String> urls = List.of("http://api1.com", "http://api2.com");
List<String> results = urls.stream()
.map(this::fetchUrl) // Не компилируется
.collect(Collectors.toList());
Это ограничение не является oversight в дизайне языка, а отражает фундаментальную несовместимость checked-исключений с функциональным программированием. В функциональном стиле функции рассматриваются как значения, которые можно передавать, комбинировать и композировать. Checked-исключения нарушают эту композицию, требуя явной обработки на каждом уровне трансформации.
Стратегия первая: обёртка в try-catch внутри лямбды
Наиболее прямолинейный подход — обернуть вызов метода с checked-исключением в try-catch блок внутри лямбды и транслировать checked в unchecked:
List<String> results = urls.stream()
.map(url -> {
try {
return fetchUrl(url);
} catch (IOException e) {
throw new RuntimeException("Failed to fetch: " + url, e);
}
})
.collect(Collectors.toList());
Этот подход работает, но имеет серьезные недостатки. Во-первых, он загромождает код шаблонной обработкой исключений, разрушая лаконичность функционального стиля. Во-вторых, выброс RuntimeException из лямбды в Stream API прерывает весь конвейер — невозможно обработать ошибку для одного элемента и продолжить обработку остальных. В-третьих, исключение теряет семантику checked, и вызывающий код может не осознавать возможность сбоя.
Для сценариев, где требуется игнорировать ошибки и продолжить обработку, можно возвращать значение по умолчанию:
// Парсинг чисел из списка строк с игнорированием ошибок
List<String> rawValues = List.of("42", "invalid", "17", "3.14", "100");
List<Integer> parsedNumbers = rawValues.stream()
.map(s -> {
try {
return Integer.parseInt(s);
} catch (NumberFormatException e) {
// Возвращаем null для невалидных значений
return null;
}
})
.filter(Objects::nonNull)
.collect(Collectors.toList());
// Результат: [42, 17, 100]
Здесь NumberFormatException — unchecked-исключение, но паттерн применим и к checked. Фильтрация Objects::nonNull удаляет null-значения, соответствующие ошибкам парсинга. Однако этот подход имеет побочный эффект: информация об ошибках теряется без логирования.
Улучшенная версия с логированием:
List<Integer> parsedNumbers = rawValues.stream()
.map(s -> {
try {
return Integer.parseInt(s);
} catch (NumberFormatException e) {
logger.warn("Failed to parse integer from '{}'", s);
return null;
}
})
.filter(Objects::nonNull)
.collect(Collectors.toList());
#Java #для_новичков #beginner #exception
👍2
Стратегия вторая: кастомный функциональный интерфейс с throws
Для сохранения семантики checked-исключений и повторного использования обработки можно создать собственные функциональные интерфейсы, объявляющие throws:
Однако эти интерфейсы несовместимы со стандартным Stream API. Для интеграции требуется обёртка, транслирующая кастомный интерфейс в стандартный:
Этот подход сохраняет чистоту вызова, но по-прежнему теряет checked-семантику на границе обёртки.
#Java #для_новичков #beginner #exception
Для сохранения семантики checked-исключений и повторного использования обработки можно создать собственные функциональные интерфейсы, объявляющие throws:
@FunctionalInterface
public interface ThrowingFunction<T, R, E extends Exception> {
R apply(T t) throws E;
}
@FunctionalInterface
public interface ThrowingConsumer<T, E extends Exception> {
void accept(T t) throws E;
}
@FunctionalInterface
public interface ThrowingSupplier<T, E extends Exception> {
T get() throws E;
}
Эти интерфейсы позволяют объявлять методы, принимающие функциональные объекты с checked-исключениями:
java
Copy
public <T, R, E extends Exception> List<R> mapWithException(
List<T> list,
ThrowingFunction<T, R, E> function) throws E {
List<R> result = new ArrayList<>();
for (T item : list) {
result.add(function.apply(item));
}
return result;
}
// Использование
List<String> urls = List.of("http://api1.com", "http://api2.com");
try {
List<String> contents = mapWithException(urls, this::fetchUrl);
} catch (IOException e) {
// Обработка ошибки
}
Однако эти интерфейсы несовместимы со стандартным Stream API. Для интеграции требуется обёртка, транслирующая кастомный интерфейс в стандартный:
public static <T, E extends Exception> Consumer<T> throwingConsumerWrapper(
ThrowingConsumer<T, E> throwingConsumer) {
return item -> {
try {
throwingConsumer.accept(item);
} catch (Exception ex) {
throw new RuntimeException(ex);
}
};
}
// Использование
urls.forEach(throwingConsumerWrapper(url -> {
writeToFile(url); // Метод, объявляющий throws IOException
}));
Этот подход сохраняет чистоту вызова, но по-прежнему теряет checked-семантику на границе обёртки.
#Java #для_новичков #beginner #exception
👍2
Стратегия третья: sneaky throws
Sneaky throws — техника, позволяющая выбросить checked-исключение без объявления его в сигнатуре метода, используя особенности generics и стирания типов в Java:
Механизм работает благодаря стиранию типов: компилятор не может проверить, что E не является RuntimeException, поэтому разрешает выброс без throws. Однако это крайне опасная практика. Вызывающий код не знает о возможности checked-исключения и не обрабатывает его. JVM вынуждена обрабатывать исключение как unchecked, что нарушает контракт типов и может привести к непредсказуемому поведению при межпроцессном взаимодействии или сериализации.
Sneaky throws оправдан только в крайне специфических сценариях: библиотечный код, полностью контролирующий контекст выполнения, или временный рефакторинг legacy-систем. В production-коде этот паттерн следует избегать.
Стратегия четвертая: Either и Try из функциональных библиотек
Наиболее элегантный подход для функциональной обработки ошибок — использование типов-результатов из библиотек вроде Vavr или самостоятельная реализация. Вместо выброса исключений метод возвращает объект, явно моделирующий два состояния: успех или ошибку.
Применение для парсинга с сохранением ошибок:
Этот подход полностью устраняет исключения из потока управления, превращая их в значения. Клиентский код вынужден обрабатывать оба случая, что устраняет риск "забытого catch". Библиотека Vavr предоставляет готовую реализацию io.vavr.control.Either и io.vavr.control.Try с богатым API для композиции и обработки результатов.
#Java #для_новичков #beginner #exception
Sneaky throws — техника, позволяющая выбросить checked-исключение без объявления его в сигнатуре метода, используя особенности generics и стирания типов в Java:
@SuppressWarnings("unchecked")
public static <E extends Throwable> void sneakyThrow(Throwable e) throws E {
throw (E) e;
}
// Использование в лямбде
List<String> results = urls.stream()
.map(url -> {
try {
return fetchUrl(url);
} catch (IOException e) {
sneakyThrow(e); // Компилятор не требует throws
return null; // Недостижимый код, необходим для компиляции
}
})
.collect(Collectors.toList());Механизм работает благодаря стиранию типов: компилятор не может проверить, что E не является RuntimeException, поэтому разрешает выброс без throws. Однако это крайне опасная практика. Вызывающий код не знает о возможности checked-исключения и не обрабатывает его. JVM вынуждена обрабатывать исключение как unchecked, что нарушает контракт типов и может привести к непредсказуемому поведению при межпроцессном взаимодействии или сериализации.
Sneaky throws оправдан только в крайне специфических сценариях: библиотечный код, полностью контролирующий контекст выполнения, или временный рефакторинг legacy-систем. В production-коде этот паттерн следует избегать.
Стратегия четвертая: Either и Try из функциональных библиотек
Наиболее элегантный подход для функциональной обработки ошибок — использование типов-результатов из библиотек вроде Vavr или самостоятельная реализация. Вместо выброса исключений метод возвращает объект, явно моделирующий два состояния: успех или ошибку.
// Упрощенная реализация Either (левая сторона — ошибка, правая — успех)
public class Either<L, R> {
private final L left;
private final R right;
private final boolean isLeft;
private Either(L left, R right, boolean isLeft) {
this.left = left;
this.right = right;
this.isLeft = isLeft;
}
public static <L, R> Either<L, R> left(L value) {
return new Either<>(value, null, true);
}
public static <L, R> Either<L, R> right(R value) {
return new Either<>(null, value, false);
}
public boolean isLeft() { return isLeft; }
public boolean isRight() { return !isLeft; }
public L getLeft() { return left; }
public R getRight() { return right; }
}
Применение для парсинга с сохранением ошибок:
public Either<String, Integer> parseInteger(String input) {
try {
return Either.right(Integer.parseInt(input));
} catch (NumberFormatException e) {
return Either.left("Invalid number format: " + input);
}
}
// Обработка в Stream API
List<String> rawValues = List.of("42", "invalid", "17", "not_a_number", "100");
List<Either<String, Integer>> results = rawValues.stream()
.map(this::parseInteger)
.collect(Collectors.toList());
List<Integer> successes = results.stream()
.filter(Either::isRight)
.map(Either::getRight)
.collect(Collectors.toList());
List<String> failures = results.stream()
.filter(Either::isLeft)
.map(Either::getLeft)
.collect(Collectors.toList());Этот подход полностью устраняет исключения из потока управления, превращая их в значения. Клиентский код вынужден обрабатывать оба случая, что устраняет риск "забытого catch". Библиотека Vavr предоставляет готовую реализацию io.vavr.control.Either и io.vavr.control.Try с богатым API для композиции и обработки результатов.
#Java #для_новичков #beginner #exception
👍2