Java for Beginner
870 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
Вакансия.

Я вот чего-то в этой жизни не понимаю.

Как у джуна может быть 2-3 года опыта с высоконагруженными приложениями?

Kafka/RabbitMQ....

предстоит заниматься: Проводить перекрестный в code review; - это издёвка такая? Как джун может проводить перекрестное code review?

"ЧТО У ВАС ТУТ ПРОИСХОДИТ ?!" - спрашиваю как герой смешного мема.

Но мне бл не смешно как то.

Я по приколу откликнулся - уверен что получу ботовский отказ))))
😱8
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апреля
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
А я сегодня не программировал)) почти…

Отдыхал с семьей в парке, ловил первое теплое, сибирское солнце 😎

Вот вам белочку, которая пришла сама 🐿️ для настроения🤝
🔥10
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апреля
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 или ручное управление.

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
Что выведет код?

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
👍2
Что такое package в Java? Зачем они нужны? 🤓

Ответ:

package
— это механизм группировки классов и интерфейсов.

Назначение:

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апреля
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.

// Метод с 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:
@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:
@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
Практический пример: парсинг чисел с игнорированием ошибок

Объединим подходы в комплексном примере. Задача: преобразовать список строк в список целых чисел, игнорируя невалидные значения и логируя ошибки.
public class NumberParser {
private static final Logger logger = LoggerFactory.getLogger(NumberParser.class);

// Стратегия: обёртка с возвратом Optional
public List<Integer> parseAllIgnoringErrors(List<String> inputs) {
return inputs.stream()
.map(this::safeParse)
.flatMap(Optional::stream) // Java 9+: фильтрация пустых Optional
.collect(Collectors.toList());
}

private Optional<Integer> safeParse(String input) {
try {
return Optional.of(Integer.parseInt(input.trim()));
} catch (NumberFormatException e) {
logger.warn("Skipping invalid number: '{}'", input);
return Optional.empty();
}
}

// Стратегия: разделение на успешные и неуспешные
public ParseResult parseAllWithDetails(List<String> inputs) {
Map<Boolean, List<Either<String, Integer>>> partitioned = inputs.stream()
.map(this::parseWithError)
.collect(Collectors.partitioningBy(Either::isRight));

List<Integer> numbers = partitioned.get(true).stream()
.map(Either::getRight)
.collect(Collectors.toList());

List<String> errors = partitioned.get(false).stream()
.map(Either::getLeft)
.collect(Collectors.toList());

return new ParseResult(numbers, errors);
}

private Either<String, Integer> parseWithError(String input) {
try {
return Either.right(Integer.parseInt(input.trim()));
} catch (NumberFormatException e) {
return Either.left(input);
}
}

public record ParseResult(List<Integer> numbers, List<String> failedInputs) {}
}



Первый метод parseAllIgnoringErrors использует Optional для фильтрации ошибок — подход, нативно поддерживаемый Java. Второй метод parseAllWithDetails сохраняет информацию о неудачах для последующего анализа или отчетности.


Часть вторая. Исключения в конструкторах и статических блоках

Конструктор в Java — это специальный метод, вызываемый при создании объекта оператором new. Если конструктор выбрасывает исключение, объект не создается. Это фундаментальное свойство имеет важное следствие: ресурсы, выделенные внутри конструктора до момента исключения, не требуют закрытия через try-finally или try-with-resources, потому что объект не существует и не будет существовать.

public class FileProcessor {
private final FileInputStream inputStream;
private final BufferedReader reader;

public FileProcessor(String path) throws FileNotFoundException {
// Если new FileInputStream выбросит исключение,
// объект FileProcessor не будет создан
this.inputStream = new FileInputStream(path);

// Эта строка выполнится только если FileInputStream создан успешно
this.reader = new BufferedReader(new InputStreamReader(inputStream));
}
}



#Java #для_новичков #beginner #exception
👍2
В этом примере, если new FileInputStream(path) выбросит FileNotFoundException, конструктор прервется, объект FileProcessor не будет инстанцирован, и reader не будет создан. Никаких утечек ресурсов не происходит, так как FileInputStream сам не был создан.

Однако если конструктор выделяет несколько ресурсов последовательно, ситуация усложняется:
public class MultiResourceProcessor {
private final Connection connection;
private final Statement statement;
private final ResultSet resultSet;

public MultiResourceProcessor(String query) throws SQLException {
this.connection = DriverManager.getConnection(DB_URL);
this.statement = connection.createStatement();
this.resultSet = statement.executeQuery(query);
}
}


Если statement.executeQuery(query) выбросит SQLException, объект MultiResourceProcessor не будет создан, но connection и statement уже были созданы и останутся незакрытыми. Это классический сценарий утечки ресурсов в конструкторе.

Решение — использование локальных переменных и try для гарантии закрытия частично созданных ресурсов:
public MultiResourceProcessor(String query) throws SQLException {
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;

try {
conn = DriverManager.getConnection(DB_URL);
stmt = conn.createStatement();
rs = stmt.executeQuery(query);

// Все ресурсы созданы успешно — присваиваем полям
this.connection = conn;
this.statement = stmt;
this.resultSet = rs;
} catch (SQLException e) {
// Закрытие частично созданных ресурсов
if (rs != null) try { rs.close(); } catch (SQLException ignored) {}
if (stmt != null) try { stmt.close(); } catch (SQLException ignored) {}
if (conn != null) try { conn.close(); } catch (SQLException ignored) {}
throw e;
}
}



Этот паттерн гарантирует, что любые ресурсы, созданные до возникновения исключения, будут закрыты. Однако он чрезвычайно многословен. Современный подход — отказ от сложной инициализации в конструкторе и использование фабричных методов:
public class MultiResourceProcessor {
private final Connection connection;
private final Statement statement;
private final ResultSet resultSet;

private MultiResourceProcessor(Connection connection, Statement statement, ResultSet resultSet) {
this.connection = connection;
this.statement = statement;
this.resultSet = resultSet;
}

public static MultiResourceProcessor create(String query) throws SQLException {
try (Connection conn = DriverManager.getConnection(DB_URL);
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(query)) {

// ResultSet не закроется при выходе из try, так как мы его возвращаем
// Это требует специальной обработки — см. ниже
return new MultiResourceProcessor(conn, stmt, rs);
}
}
}


Важное ограничение: try-with-resources закроет ресурсы при выходе из блока, поэтому возврат ResultSet из фабричного метода требует отказа от автоматического закрытия или использования специальных оберток. В большинстве случаев лучше отложить создание ресурсов до момента фактического использования, а не выполнять их в конструкторе.


#Java #для_новичков #beginner #exception
👍2
Исключения в статических блоках

Статический блок инициализации выполняется при загрузке класса JVM, до создания любых экземпляров. Если в процессе выполнения статического блока или инициализации статической переменной возникает исключение, JVM автоматически оборачивает его в ExceptionInInitializerError.
public class ConfigHolder {
private static final Map<String, String> config;

static {
config = loadConfig(); // Может выбросить RuntimeException
}

private static Map<String, String> loadConfig() {
throw new RuntimeException("Configuration file corrupted");
}
}


При первом обращении к классу ConfigHolder будет выброшено:
java.lang.ExceptionInInitializerError
Caused by: java.lang.RuntimeException: Configuration file corrupted


ExceptionInInitializerError наследует LinkageError, что сигнализирует о фатальной проблеме при загрузке класса. Ключевое следствие: класс, выбросивший ExceptionInInitializerError, помечается как неинициализированный и не может быть использован в дальнейшем . Все последующие попытки обращения к этому классу приведут к NoClassDefFoundError с причиной "initialization error".
// Первое обращение — ExceptionInInitializerError
try {
ConfigHolder holder = new ConfigHolder();
} catch (ExceptionInInitializerError e) {
// Обработка
}

// Второе обращение — NoClassDefFoundError, даже если причина устранена
try {
ConfigHolder holder = new ConfigHolder(); // Не работает!
} catch (NoClassDefFoundError e) {
// Класс навсегда непригоден
}


Это поведение делает ExceptionInInitializerError особенно опасным: одна ошибка при загрузке класса делает его непригодным на всю жизнь JVM. Перезагрузка класса возможна только через создание нового ClassLoader.
Checked-исключения напрямую запрещены в статических блоках. Компилятор отклонит код, пытающийся выбросить checked из static initializer:
public class InvalidStatic {
static {
throw new IOException("Not allowed"); // Ошибка компиляции
}
}



Для обработки checked-исключений в статических блоках применяется паттерн оборачивания в ExceptionInInitializerError:
public class SafeStaticInit {
private static final Properties props;

static {
try {
props = loadProperties();
} catch (IOException e) {
// Оборачиваем checked в ExceptionInInitializerError
throw new ExceptionInInitializerError(e);
}
}

private static Properties loadProperties() throws IOException {
Properties p = new Properties();
try (InputStream is = SafeStaticInit.class.getResourceAsStream("/config.properties")) {
if (is == null) {
throw new IOException("Config file not found");
}
p.load(is);
}
return p;
}
}


В этом примере IOException из loadProperties() перехватывается и оборачивается в ExceptionInInitializerError. Важно: если мы явно выбрасываем ExceptionInInitializerError, JVM не оборачивает его повторно — сохраняется чистый стектрейс . Если же мы обернем checked в RuntimeException, JVM дополнительно обернет его в ExceptionInInitializerError, создавая избыточную вложенность:
// Антипаттерн: избыточная вложенность
static {
try {
props = loadProperties();
} catch (IOException e) {
throw new RuntimeException(e); // JVM обернет в ExceptionInInitializerError
}
}
// Результат: ExceptionInInitializerError -> RuntimeException -> IOException



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

import java.util.stream.Stream;

@FunctionalInterface
interface ThrowingFunctionTask280426<T, R, E extends Exception> {
R apply(T t) throws E;
}

public class Task280426 {
public static void main(String[] args) {
try {
Stream.of("1", "2", "3")
.map(wrap(s -> throwsChecked(s)))
.forEach(System.out::print);
} catch (Exception e) {
System.out.print("Error");
}
}

static int throwsChecked(String s) throws Exception {
if (s.equals("2")) throw new Exception("boom");
return Integer.parseInt(s);
}

static <T, R> java.util.function.Function<T, R> wrap(ThrowingFunctionTask280426<T, R, Exception> f) {
return t -> {
try {
return f.apply(t);
} catch (Exception e) {
throw new RuntimeException(e);
}
};
}
}


#Tasks
👍2
Варианты ответа:
Anonymous Quiz
17%
123
17%
12Error
50%
1Error
17%
1 Exception
👍2
Как передаются аргументы в Java: по значению или по ссылке? 🤓

Ответ:

В Java аргументы всегда передаются по значению (by value).

Для примитивов передается само значение. Для объектов передается значение ссылки на объект (копия ссылки).

Это означает, что метод не может изменить оригинальную ссылку (переназначить объект), но может изменить состояние самого переданного объекта (вызвать методы, изменяющие поля).

Поэтому часто говорят "объекты передаются по значению ссылки".


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

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

Жюль Анри́ Пуанкаре́ (фр. Jules Henri Poincaré; 29 апреля 1854, Нанси, Франция — 17 июля 1912, Париж, Франция) — французский математик, механик, физик, астроном и философ.

Среди его самых крупных достижений:
Создание топологии.
Создание качественной теории дифференциальных уравнений.
Разработка теории автоморфных функций.
Разработка новых, чрезвычайно эффективных методов небесной механики.
Создание математических основ теории относительности, а также обобщение принципа относительности на все физические явления.
Наглядная модель геометрии Лобачевского (впервые встречается у Эудженио Бельтрами).



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

1913 — эмигрировавший в США шведский инженер-электрик Гидеон Сундбек получил патент на изобретение, известное сейчас как застёжка-молния.


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