Java for Beginner
871 subscribers
1.01K photos
275 videos
14 files
1.69K links
Канал от новичков для новичков!
Изучайте Java вместе с нами!
Здесь мы обмениваемся опытом и постоянно изучаем что-то новое!

Наш YouTube канал - https://www.youtube.com/@Java_Beginner-Dev

Наш канал на RUTube - https://rutube.ru/channel/37896292/
Download Telegram
История технологии сегодня — 14 апреля

ℹ️ Кто родился в этот день

Серге́й Ива́нович Мо́син (2 [14] апреля 1849, Рамонь — 26 января [8 февраля] 1902, Сестрорецк) — русский конструктор и организатор производства стрелкового оружия. Генерал-майор Русской императорской армии.

В 1883 году Мосин разработал свои первые магазинные винтовки. Так, он усовершенствовал винтовку Бердана, приделав к ней магазин на восемь патронов. 16 апреля 1891 года был утверждён образец «повторительной» четырёхтактной винтовки со серединным магазином калибра 3 линии (7,62 мм), основу которой разработал Мосин. Она получила название «Трёхлинейная винтовка образца 1891 года». В 1900 году на Всемирной выставке в Париже российская «малокалиберная» трёхлинейная штатная винтовка получила Гран-При. Винтовки и карабины системы Мосина нескольких модификаций производилась в России и СССР до 1947 года и находились на вооружении до середины 1970-х годов. После Второй мировой войны винтовки и карабины Мосина производились по лицензии в ПНР, ВНР, РНР.


Юкихиро Мацумо́то (яп. 松本行弘, чаще яп. まつもとゆきひろ, также известный как Matz, род. 14 апреля 1965) — японский разработчик свободного ПО, создатель языка программирования Ruby.

В интервью «Japan Inc.» он говорил, что сам учился программировать ещё до окончания школы. Он окончил университет города Цукуба, где он занимался исследованиями языков программирования и компиляторов. С 2006 года возглавляет отдел исследований и разработок Network Applied Communication Laboratory, японский системный интегратор свободного ПО.


Христиа́н Гю́йгенс ван Зёйлихем (нид. Christiaan Huygens МФА: [ˈkrɪstijaːn ˈɦœyɣə(n)s]о файле; 14 апреля 1629, Гаага — 8 июля 1695, там же) — голландский механик, физик, математик, астроном и изобретатель. Первый иностранный член Лондонского королевского общества (1663), член Французской академии наук с момента её основания (1666) и её первый президент (1666—1681).

Один из основоположников теоретической механики и теории вероятностей. Внёс значительный вклад в оптику, молекулярную физику, астрономию, геометрию, часовое дело. Открыл кольца Сатурна и Титан (спутник Сатурна). Изобрёл первую практически применимую модель часов с маятником. Положил начало волновой оптике.


🌐 Знаковые события

1932 — в кембриджской лаборатории Резерфорда физики Кокрофт и Уолтон впервые добились искусственной ядерной реакции.

1983 — первый радиотелефон начал продаваться в Великобритании.

2003 — учёные объявили о завершении основных работ по расшифровке
генома человека.


#Biography #Birth_Date #Events #14апреля
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Раздел 9. Исключения, логирование, отладка

Глава 1. Иерархия исключений (Exceptions)

try-catch-finally – правильная обработка и освобождение ресурсов


Исторический контекст: до Java 7


До появления Java 7 в 2011 году механизм try-catch-finally был единственным способом гарантировать выполнение cleanup-кода независимо от того, как завершился основной блок операций. Этот паттерн применялся для закрытия файловых потоков, сетевых соединений, освобождения блокировок и любых других ресурсов, требующих явного освобождения.

Однако этот подход был чрезвычайно многословным и подверженным ошибкам. Каждый ресурс требовал отдельной переменной, объявленной вне блока try, проверки на null в finally, и вложенных try-catch блоков для обработки исключений при самом закрытии ресурса. Это создавало "pyramid of doom" — визуально громоздкую структуру кода, где бизнес-логика терялась среди шаблонного кода управления ресурсами.


Механика выполнения: как JVM обрабатывает finally

На уровне байткода JVM блок finally реализован не как отдельная конструкция языка, а через механизм инлайнинга и таблиц исключений. Компилятор Java дублирует байткод finally-блока в каждой точке выхода из try и связанных catch-блоков, а также добавляет специальные записи в exception table для гарантии выполнения даже при неперехваченных исключениях.

Рассмотрим простой пример и его байткод-представление:
public void simpleTryFinally() {
try {
processData();
} finally {
cleanup();
}
}


Компилятор генерирует байткод, где инструкции cleanup() дублируются в трех местах: при нормальном завершении try, при выходе через return, и в специальном catch-all обработчике для неперехваченных исключений. Exception table метода содержит запись from: 0, to: 4, target: 8, type: any, которая перехватывает любое исключение, выполняет cleanup, и перевыбрасывает исходное исключение .

В современных версиях Java (начиная с Java 6) компилятор использует полный инлайнинг байткода finally-блока. Ранее, до Java 6, применялись мини-подпрограммы (mini-subroutines) с инструкциями jsr (jump subroutine) и ret (return from subroutine), которые вызывали общий блок кода из разных точек . Этот подход был отменен из-за сложностей верификации байткода и ограничений на оптимизацию.


Паттерн управления ресурсами: классический подход

Классический паттерн освобождения ресурсов через try-finally требовал строгой дисциплины.

Рассмотрим корректную реализацию для одного ресурса:
public String readFile(String path) throws IOException {
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(path));
return reader.readLine();
} finally {
if (reader != null) {
reader.close();
}
}
}


Этот код содержит несколько критически важных элементов. Переменная reader объявлена вне блока try для доступности в finally. Проверка на null обязательна, так как если конструктор FileReader выбросит исключение (например, файл не найден), переменная reader останется неинициализированной. Блок finally выполняется всегда, даже если readLine() выбросит исключение или метод выполнит ранний return.

Сложность экспоненциально растет с количеством ресурсов. Для двух ресурсов требуется уже четыре уровня вложенности:
public void copyFile(String sourcePath, String destPath) throws IOException {
FileInputStream fis = null;
FileOutputStream fos = null;
try {
fis = new FileInputStream(sourcePath);
try {
fos = new FileOutputStream(destPath);
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = fis.read(buffer)) != -1) {
fos.write(buffer, 0, bytesRead);
}
} finally {
if (fos != null) {
fos.close();
}
}
} finally {
if (fis != null) {
fis.close();
}
}
}


#Java #для_новичков #beginner #exception #try_catch_finally
👍4
Здесь важен порядок закрытия: ресурсы должны освобождаться в обратном порядке их создания. Вложенные try-finally обеспечивают, что fis будет закрыт даже если fos.close() выбросит исключение. Однако этот код все еще уязвим: если fis.close() выбросит исключение, оно замаскирует любое исключение из основного блока, что делает отладку чрезвычайно сложной.


Опасные взаимодействия: finally и return


Одна из наиболее коварных особенностей finally — его взаимодействие с оператором return. Блок finally выполняется после вычисления возвращаемого значения, но фактически до выхода из метода, что создает возможность для подавления или модификации результата.

Рассмотрим классический пример подавления исключения:
public int problematicMethod() {
try {
throw new RuntimeException("Critical error");
} finally {
return 42; // Исключение будет подавлено!
}
}


В этом коде исключение из try-блока никогда не достигнет вызывающего метода. JVM выполняет finally, встречает return, и завершает метод со значением 42. Это не просто плохая практика — это семантически некорректное поведение, которое нарушает контракт метода и делает невозможным обнаружение ошибок .

Другой вариант той же проблемы — модификация возвращаемого значения:
public int confusingMethod() {
int result = 0;
try {
result = 10;
return result;
} finally {
result = 20; // Это изменение проигнорируется!
}
}


Здесь метод вернет 10, а не 20. JVM сохраняет значение 10 в отдельной локальной переменной перед входом в finally, и восстанавливает его после завершения finally.

Однако если finally содержит собственный return, он переопределяет сохраненное значение:
public int anotherConfusingMethod() {
try {
return 10;
} finally {
return 20; // Теперь вернет 20
}
}


Эти примеры демонстрируют, что return в finally — это не просто code smell, а активно вредная практика, которую следует категорически запрещать в code style guidelines.


Обработка исключений при закрытии ресурсов

При закрытии ресурсов в finally возникает дополнительная проблема: сам метод close() может выбросить исключение. В классическом подходе это приводит к подавлению исходного исключения:
public void readAndProcess(String path) throws IOException {
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(path));
process(reader);
} finally {
if (reader != null) {
reader.close(); // Если здесь IOException, исходное исключение потеряно
}
}
}


Если process(reader) выбросит DataFormatException, а reader.close() выбросит IOException, вызывающий метод получит только IOException. Информация о реальной причине ошибки (некорректный формат данных) будет утрачена. Это критично для диагностики проблем в production.

Для сохранения исходного исключения требовался изощренный паттерн:
public void readAndProcessSafe(String path) throws IOException {
BufferedReader reader = null;
IOException originalException = null;
try {
reader = new BufferedReader(new FileReader(path));
process(reader);
} catch (IOException e) {
originalException = e;
throw e;
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException closeException) {
if (originalException != null) {
originalException.addSuppressed(closeException);
} else {
throw closeException;
}
}
}
}
}


Этот код использует механизм suppressed exceptions, появившийся в Java 7, но реализованный вручную. Он сохраняет ссылку на исходное исключение, и при возникновении исключения при закрытии добавляет его как "подавленное" к исходному. Это сохраняет полную картину ошибки, но ценой чрезвычайной сложности кода.


#Java #для_новичков #beginner #exception #try_catch_finally
👍3
Статические инициализаторы: особый случай

В статических блоках инициализации классов try-finally применяется редко, но имеет особую семантику. Если в статическом блоке возникает исключение, JVM оборачивает его в ExceptionInInitializerError, и класс помечается как неинициализированный. Последующие попытки использовать класс приводят к NoClassDefFoundError с причиной "initialization error".
public class ResourceHolder {
private static final Connection connection;

static {
Connection temp = null;
try {
temp = createConnection();
initializeSchema(temp);
} finally {
if (temp != null) {
try {
temp.close();
} catch (SQLException e) {
// Логирование, но исключение не пробрасывается
// Иначе класс станет непригодным к использованию
logger.error("Failed to close connection during initialization", e);
}
}
}
connection = temp; // Этот код никогда не выполнится, если finally выбросит исключение
}
}


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


Практические рекомендации по использованию

Несмотря на появление try-with-resources, понимание try-finally остается необходимым для работы с legacy-кодом, кастомными ресурсами без AutoCloseable, и сценариями, требующими сложной логики cleanup.
Правило первое: никогда не используйте return в finally. Это подавляет исключения и создает непредсказуемое поведение. Если cleanup должен влиять на возвращаемое значение, пересмотрите архитектуру метода — возможно, логика cleanup должна быть вынесена в вызывающий код.
Правило второе: проверяйте переменные на null перед использованием в finally. Ресурс может не быть создан, если конструктор выбросил исключение, но finally выполнится в любом случае.
Правило третье: сохраняйте исходные исключения при cleanup. Если finally может выбросить исключение, используйте механизм suppressed exceptions (в Java 7+) или логируйте исходное исключение перед повторным выбросом.
Правило четвертое: минимизируйте код в finally. Блок finally должен содержать только cleanup-операции, критичные для корректности системы. Никакой бизнес-логики, никаких операций, которые могут fail — только освобождение ресурсов.
Правило пятое: предпочитайте специфичные catch-блоки общим. Перехват Exception или Throwable в catch перед finally может привести к непреднамеренному подавлению ошибок. Будьте максимально конкретны в типах перехватываемых исключений.


#Java #для_новичков #beginner #exception #try_catch_finally
👍5
Что выведет код?

public class Task140426 {
public static void main(String[] args) {
System.out.println(test());
}

static int test() {
try {
return 1;
} catch (Exception e) {
return 2;
} finally {
return 3;
}
}
}


#Tasks
👍3🤯3
Варианты ответа:
Anonymous Quiz
38%
1
0%
2
57%
3
5%
Ошибка компиляции
4👍2
Какие виды исключений в Java вы знаете (иерархия)? 🤓

Ответ:

Все исключения являются наследниками класса Throwable.

Он делится на два основных подкласса:
Error — критические ошибки JVM, которые обычно не обрабатывают (OutOfMemoryError, StackOverflowError).

Exception — исключения, которые важны для приложения. Exception делится на checked (проверяемые) — обязаны быть обработаны или объявлены в throws (IOException, SQLException), и unchecked (runtime) — наследники RuntimeException, могут не обрабатываться (NullPointerException, IllegalArgumentException).


#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
История технологии сегодня — 15 апреля

ℹ️ Кто родился в этот день

Васи́лий Я́ковлевич Стру́ве (нем. Friedrich Georg Wilhelm Struve; 15 апреля 1793, Альтона, Германия — 11 [23] ноября 1864, Санкт-Петербург) — русско-немецкий астроном, один из основоположников звёздной астрономии в России. В области звёздной астрономии Струве открыл реальное сгущение звёзд к центральным частям Галактики и обосновал вывод о существовании и величине межзвёздного поглощения света. Много времени уделял Струве изучению двойных звёзд. Составленные им два каталога двойных звёзд были опубликованы в 1827 и 1852 годах. Струве принадлежит одно из первых в истории (1837) успешное измерение годичного параллакса звезды (Веги в созвездии Лиры). В середине XIX века участвовал в создании Лиссабонской астрономической обсерватории.


🌐 Знаковые события

1998 — на одном из заводов Intel изготовлен последний кристалл для процессора класса Pentium. Intel окончательно переходит с производства процессоров с архитектурой P5 под разъём Socket 7 на выпуск процессоров с архитектурой P6 для разъёма Slot 1. Официально объявлен новый процессор для «массовых» пользователей — Celeron.

2005 — с космодрома Байконур запущен космический корабль «Союз ТМА-6».


#Biography #Birth_Date #Events #15апреля
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
[Совет по Java #026]

Тема: Синхронизация (synchronized) по строковой константе опасна.

Проблема: Строковые литералы и строки, полученные через intern(), попадают в пул строк (String Pool) и могут быть переиспользованы по всей JVM.

Если синхронизироваться на строковой константе, например synchronized("LOCK"), то блокировка становится глобальной для всего приложения. Любая другая часть кода, синхронизирующаяся на той же строке (даже по ошибке), будет конкурировать за один и тот же монитор.

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

Решение: Никогда не используйте строки в качестве объектов блокировки.

Всегда создавайте выделенный private final Object для синхронизации. Если требуется блокировка по имени ресурса, используйте ConcurrentHashMap с созданием уникальных объектов блокировки под каждое имя.

public class StringLockExample {

//Антипаттерн: синхронизация по строковой константе
private static final String LOCK = "LOCK"; // Попадает в пул строк

public void badMethod() {
synchronized (LOCK) { // Опасно! Другие модули могут использовать LOCK
// критическая секция
}
}

//Еще хуже: синхронизация по литералу
public void evenWorse() {
synchronized ("LOCK") { // Каждый раз один и тот же объект из пула
// Эта блокировка глобальна для всей JVM
}
}

//Решение 1: выделенный объект для блокировки
private final Object lock = new Object(); // Уникальный объект

public void goodMethod() {
synchronized (lock) {
// Только этот класс использует эту блокировку
}
}

//Решение 2: блокировка по имени с уникальными объектами
private final ConcurrentHashMap<String, ReentrantLock> lockMap = new ConcurrentHashMap<>();

public void lockByName(String resourceId) {
ReentrantLock lock = lockMap.computeIfAbsent(resourceId, k -> new ReentrantLock());
lock.lock();
try {
// работа с ресурсом resourceId
} finally {
lock.unlock();
}
}

//Решение 3: использование ReentrantLock с выделенным объектом
private final ReentrantLock reentrantLock = new ReentrantLock();

public void withReentrantLock() {
reentrantLock.lock();
try {
} finally {
reentrantLock.unlock();
}
}

// Демонстрация проблемы
public static void main(String[] args) {
// Модуль A
Thread t1 = new Thread(() -> {
synchronized ("SHARED") {
System.out.println("Модуль A захватил блокировку");
try { Thread.sleep(1000); } catch (InterruptedException e) {}
}
});

// Модуль B (совершенно другой класс, другая команда)
Thread t2 = new Thread(() -> {
synchronized ("SHARED") { // Та же строка из пула!
System.out.println("Модуль B захватил блокировку");
}
});

t1.start();
t2.start(); // Будет ждать, пока t1 не отпустит блокировку
// Два несвязанных модуля блокируют друг друга!
}
}


Объяснение: Строковые литералы интернируются автоматически. Это означает, что "LOCK" в одном месте и "LOCK" в другом — это один и тот же объект в памяти. Синхронизация по такому объекту создает глобальную блокировку на всю JVM, что может вызвать неожиданные взаимоблокировки между абсолютно несвязанными компонентами. Даже строки, созданные через new String("LOCK") без вызова intern(), могут быть проблемой, если где-то используется литерал.

Пул строк предназначен для экономии памяти, а не для синхронизации. Правильная практика — создавать приватные финальные объекты-заглушки private final Object lock = new Object(). Для блокировки по ключу используйте ConcurrentHashMap с ReentrantLock или synchronized(lockMap.computeIfAbsent(...)).

#Java #советы
👍5
Что выведет код?

public class Task150426 {
private static final String LOCK = "LOCK";

public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(() -> {
synchronized (LOCK) {
System.out.print("A");
try { Thread.sleep(100); } catch (InterruptedException e) {}
System.out.print("B");
}
});

Thread t2 = new Thread(() -> {
synchronized ("LOCK") {
System.out.print("C");
System.out.print("D");
}
});

t1.start();
t2.start();
}
}


#Tasks
👍2
👍2
Как создать свой класс исключения? 🤓

Ответ:

Чтобы создать свое исключение, нужно унаследоваться от соответствующего класса в иерархии Throwable.

Для проверяемого (checked) исключения — расширять Exception (или его подкласс).

Для непроверяемого (unchecked) — расширять RuntimeException.

Рекомендуется создать несколько конструкторов (по умолчанию, с сообщением, с причиной — Throwable cause, комбинированный) и переиспользовать конструкторы суперкласса. Хорошая практика — делать класс исключения финальным или, по крайней мере, правильно документировать.


#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
История технологии сегодня — 16 апреля

ℹ️ Кто родился в этот день

Алекса́ндр Ива́нович Макаре́вский (3 [16] апреля 1904, село Мушковичи, Смоленская губерния — 11 мая 1979, Москва) советский учёный в области прочности и аэроупругости летательных аппаратов. Свыше тридцати лет он руководил исследованиями ЦАГИ в области прочности. Под его руководством по существу сформировались основные разделы науки о прочности самолётов: статическая прочность, нормы прочности, оценка долговечности конструкций или ресурса, аэроупругость. Будучи учёным широкого профиля, внёс личный вклад во все эти разделы.

Уилбер Райт (англ. Wilbur Wright (1867—1912) американский изобретатель, авиаконструктор, лётчик, старший из братьев — пионеров воздухоплавания. Фундаментальное достижение братьев Райт — практичные системы управления и устойчивости по трём осям вращения самолёта, чтобы эффективно управлять самолётом и поддерживать его равновесие во время полёта. Их подход стал основой для конструирования и постройки самолётов. Братья Райт сосредоточились на изучении вопросов управления летящим аппаратом, вместо того, чтобы находить возможность устанавливать более мощные двигатели, как это делали другие экспериментаторы. Их эксперименты в аэродинамической трубе оказались плодотворнее, чем эксперименты других пионеров авиации, для создания эффективного крыла и пропеллеров.

Джон Хэдли (англ. John Hadley, рус. Гадле́й; 16 апреля 1682 — 14 февраля 1744) — английский математик, более всего известный изобретением октанта, предшественника секстанта, около 1730 года. Американец Томас Годфри изобрёл октант примерно в то же время и независимо от него.

Алексе́й Леони́дович Па́житнов (род. 16 апреля 1955, Москва, РСФСР, СССР)
— советский и американский программист и геймдизайнер. Наиболее известен тем, что в 1984 году, работая в Вычислительном центре им. Дородницына при Академии наук СССР, спроектировал и разработал игру «Тетрис».


🌐 Знаковые события

1863 — во Франции спущена на воду Plongeur (с фр. — «Ныряльщик») — самая большая подводная лодка XIX века.

1906 — завершена прокладка подводного телеграфного кабеля между США и Китаем.

1972 — стартовала пятая экспедиция по программе «Аполлон» с высадкой на поверхность Луны (состоявшейся 20 апреля); командир — астронавт Джон Янг.



#Biography #Birth_Date #Events #16апреля
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Раздел 9. Исключения, логирование, отладка

Глава 1. Иерархия исключений (Exceptions)

try-with-resources (Java 7+) – автоматическое закрытие AutoCloseable

До Java 7 управление ресурсами в Java было многословным и подверженным ошибкам. Каждый ресурс требовал явного закрытия в блоке finally, что приводило к "pyramid of doom" — вложенным структурам, где бизнес-логика терялась среди шаблонного кода. Попытка закрыть ресурс в finally могла привести к подавлению исключений: если основной блок и finally выбрасывали исключения, вызывающий код получал только исключение из finally, а оригинальная ошибка терялась .

Java 7 представила конструкцию try-with-resources — синтаксический сахар, который автоматизирует закрытие ресурсов и решает проблему подавления исключений через механизм suppressed exceptions. Это изменение было частью более широкого проекта Project Coin, направленного на повышение производительности разработчика через небольшие, но значимые улучшения языка.


Интерфейс AutoCloseable: контракт для ресурсов

Центральным элементом try-with-resources является интерфейс java.lang.AutoCloseable, введенный в Java 7 специально для поддержки этой конструкции.

Интерфейс объявляет единственный метод:
void close() throws Exception;


Ключевое отличие от старого интерфейса java.io.Closeable (JDK 5) — тип выбрасываемого исключения. Closeable.close() ограничен IOException, что делает его непригодным для ресурсов, требующих выброса других checked-исключений, таких как java.sql.Connection с его SQLException . Чтобы сохранить обратную совместимость, Closeable был модифицирован для наследования от AutoCloseable, переопределяя close() с более специфичным IOException.

Важные различия между интерфейсами:
Идемпотентность: Closeable требует, чтобы повторный вызов close() не имел эффекта; AutoCloseable не гарантирует этого, хотя настоятельно рекомендует
Тип исключения: Closeable — только IOException, AutoCloseable — любое Exception
Предназначение: Closeable специфичен для I/O, AutoCloseable — универсальный механизм для любых ресурсов

Документация Oracle рекомендует реализациям AutoCloseable не выбрасывать InterruptedException из close(), так как это взаимодействует со статусом прерывания потока и может привести к runtime-проблемам при подавлении исключения.


Базовый синтаксис и семантика

Конструкция try-with-resources объявляет ресурсы в круглых скобках сразу после ключевого слова try. Каждый ресурс должен реализовывать AutoCloseable или Closeable:
static String readFirstLineFromFile(String path) throws IOException {
try (BufferedReader br = new BufferedReader(new FileReader(path))) {
return br.readLine();
}
}


В этом примере BufferedReader автоматически закрывается при выходе из блока try, независимо от того, как завершилось выполнение — нормально или через исключение. Переменная br является неявно final и доступна только внутри блока try.

Компилятор генерирует байткод, эквивалентный следующей структуре:
// Псевдокод, демонстрирующий трансформацию компилятором
BufferedReader br = new BufferedReader(new FileReader(path));
Throwable primaryException = null;
try {
return br.readLine();
} catch (Throwable t) {
primaryException = t;
throw t;
} finally {
if (br != null) {
if (primaryException != null) {
try {
br.close();
} catch (Throwable suppressed) {
primaryException.addSuppressed(suppressed);
}
} else {
br.close();
}
}
}


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


#Java #для_новичков #beginner #exception #try_with_resources
👍4
Механизм suppressed exceptions

Когда исключение возникает как в основном блоке try, так и при закрытии ресурса, try-with-resources сохраняет оба исключения. Исключение из основного блока становится primary exception, а исключение из close() — suppressed exception, добавляемое к primary через метод Throwable.addSuppressed().

Пример демонстрирует это поведение:

public class ExceptionalResource implements AutoCloseable {
public void process() {
throw new IllegalArgumentException("Error in process()");
}

@Override
public void close() {
throw new NullPointerException("Error in close()");
}
}

public static void demoSuppressedException() throws Exception {
try (ExceptionalResource resource = new ExceptionalResource()) {
resource.process();
}
}


При вызове demoSuppressedException() будет выброшено IllegalArgumentException из process(), а NullPointerException из close() будет доступно как подавленное исключение:
try {
demoSuppressedException();
} catch (Exception e) {
assert e instanceof IllegalArgumentException;
assert e.getMessage().equals("Error in process()");
assert e.getSuppressed().length == 1;
assert e.getSuppressed()[0] instanceof NullPointerException;
}


Это поведение противоположно классическому try-finally, где исключение из finally подавляет исключение из try. Методы Throwable.getSuppressed() и addSuppressed() были добавлены в Java 7 специально для поддержки этой функциональности.


Множественные ресурсы и порядок закрытия

try-with-resources поддерживает объявление нескольких ресурсов, разделенных точкой с запятой:
public void copyFile(String sourcePath, String destPath) throws IOException {
try (FileInputStream fis = new FileInputStream(sourcePath);
FileOutputStream fos = new FileOutputStream(destPath)) {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = fis.read(buffer)) != -1) {
fos.write(buffer, 0, bytesRead);
}
}
}


Ресурсы закрываются в обратном порядке их объявления: сначала fos, затем fis . Этот порядок критичен для корректного освобождения зависимых ресурсов — например, BufferedReader должен быть закрыт до закрытия underlying FileReader.

Если при закрытии нескольких ресурсов возникают исключения, все они добавляются как suppressed к primary exception:
try (Resource r1 = new Resource(); 
Resource r2 = new Resource()) {
throw new PrimaryException();
}
// Если r1.close() и r2.close() оба выбрасывают исключения,
// PrimaryException будет иметь два suppressed исключения



#Java #для_новичков #beginner #exception #try_with_resources
👍3
Интеграция с catch и finally

try-with-resources может сочетаться с традиционными catch и finally блоками. В этом случае ресурсы закрываются перед выполнением catch, а finally выполняется после закрытия всех ресурсов:
try (Resource resource = new Resource()) {
resource.process();
} catch (ProcessingException e) {
// Выполняется после закрытия resource
logger.error("Processing failed", e);
// Доступны suppressed исключения из resource.close()
for (Throwable suppressed : e.getSuppressed()) {
logger.warn("Suppressed during close", suppressed);
}
} finally {
// Выполняется после catch, ресурсы уже закрыты
metrics.incrementOperationCounter();
}


Важный нюанс: если явный finally блок выбрасывает исключение, оно подавляет все предыдущие исключения, включая primary и suppressed из try-with-resources . Это сохраняет семантику finally как последней инстанции.


Создание кастомных ресурсов

Любой класс, требующий явного cleanup, может реализовать AutoCloseable для интеграции с try-with-resources:
public class DatabaseConnectionPool implements AutoCloseable {
private final List<Connection> availableConnections;
private final List<Connection> inUseConnections;
private boolean closed = false;

public DatabaseConnectionPool(int size) {
this.availableConnections = new ArrayList<>(size);
this.inUseConnections = new ArrayList<>();
// Инициализация пула
}

public Connection acquireConnection() {
ensureOpen();
// Логика выдачи соединения
}

public void releaseConnection(Connection conn) {
ensureOpen();
// Логика возврата соединения
}

@Override
public void close() {
if (closed) {
return; // Идемпотентность рекомендуется
}
closed = true;

// Закрытие всех соединений
for (Connection conn : availableConnections) {
silentlyClose(conn);
}
for (Connection conn : inUseConnections) {
silentlyClose(conn);
}
}

private void ensureOpen() {
if (closed) {
throw new IllegalStateException("Pool is closed");
}
}

private void silentlyClose(Connection conn) {
try {
conn.close();
} catch (SQLException e) {
// Логирование, но не выброс — не блокируем закрытие остальных
logger.warn("Failed to close connection", e);
}
}
}


Использование:
public void processBatch(List<String> queries) {
try (DatabaseConnectionPool pool = new DatabaseConnectionPool(10)) {
for (String query : queries) {
Connection conn = pool.acquireConnection();
try {
executeQuery(conn, query);
} finally {
pool.releaseConnection(conn);
}
}
} // pool автоматически закрывается, все соединения освобождаются
}


Ограничения и особые случаи

Ресурсы, объявленные в try-with-resources, являются неявно final и не могут быть переназначены внутри блока . Это предотвращает случайную потерю ссылки на ресурс до его автоматического закрытия.
Если конструктор ресурса выбрасывает исключение, ресурс не добавляется в список для закрытия, и исключение распространяется как обычно. Это безопасно, так как ресурс не был создан.


#Java #для_новичков #beginner #exception #try_with_resources
👍5
Что выведет код?

public class Task160426 {
static class CloseableCounter160426 implements AutoCloseable {
private String id;
public CloseableCounter160426(String id) { this.id = id; }
public void close() throws Exception {
System.out.print(id);
throw new RuntimeException("close error: " + id);
}
}

public static void main(String[] args) {
try (CloseableCounter160426 c1 = new CloseableCounter160426("A");
CloseableCounter160426 c2 = new CloseableCounter160426("B")) {
throw new RuntimeException("body error");
} catch (Exception e) {
System.out.print(e.getMessage());
for (Throwable suppressed : e.getSuppressed()) {
System.out.print(suppressed.getMessage());
}
}
}
}


#Tasks
👍1
Что такое invokedynamic и зачем он нужен? 🤓

Ответ:

invokedynamic
(появился в Java 7) — это новая инструкция байт-кода, которая позволяет динамически связывать вызов метода в рантайме, а не на этапе компиляции.

Это ключевой механизм для реализации динамических языков на JVM.

В Java 8+ invokedynamic используется для реализации лямбда-выражений — вместо генерации анонимных классов на этапе компиляции, лямбды связываются динамически, что улучшает производительность и гибкость.


#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
История технологии сегодня — 17 апреля

ℹ️ Кто родился в этот день

Джованни Баттиста Риччоли (итал. Giovanni Battista Riccioli; 17 апреля 1598, Феррара — 25 июня 1671, Болонья) — итальянский астроном и теолог, автор труда «Новый Альмагест» (Almagestum Novum) — свода астрономических знаний своего времени. Вместе с Франческо Гримальди составил карту Луны и ввёл в практику обозначение лунных кратеров именами учёных.


🌐 Знаковые события

2014 – космический телескоп НАСА « Кеплер» подтвердил открытие первой планеты размером с Землю в обитаемой зоне другой звезды.


#Biography #Birth_Date #Events #17апреля
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3