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

import java.io.*;
import java.nio.charset.StandardCharsets;

public class Task190626 {
public static void main(String[] args) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
OutputStreamWriter writer = new OutputStreamWriter(baos, StandardCharsets.US_ASCII);
writer.write('€');
writer.flush();

ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
InputStreamReader reader = new InputStreamReader(bais, StandardCharsets.US_ASCII);
int ch = reader.read();
System.out.println(ch);
}
}


#Tasks
👍2
Варианты ответа:
Anonymous Quiz
30%
63
10%
8364
0%
-1
60%
Исключение
👍3
Что такое JNI? Какие проблемы при его использовании? 🤓

Ответ:

JNI (Java Native Interface)
— это фреймворк, позволяющий Java-коду вызывать и быть вызванным нативными приложениями (C/C++).

Используется для доступа к системным функциям, устройствам, оптимизации.

Проблемы:
1) потеря переносимости (нужно компилировать под каждую ОС/архитектуру).
2) сложность отладки (ошибки в нативном коде могут крашнуть JVM).
3) утечки памяти в нативной части не отслеживаются GC.
4) накладные расходы на маршалинг данных.
5) несовместимость с модульной системой Java 9+.

Альтернативы: Project Panama (Foreign Function API) в новых версиях Java.



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

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

Давид Каждан ( иврит : דוד קשדן ), урожденный Дмитрий Александрович Каждан ( русский : Дмитрий Александрович Каждан ; родился 20 июня 1946 года) — советский и израильский математик, известный своими работами в области теории представлений . Каждан является стипендиатом Макартура 1990 года . В 2012 году он получил Премию Израиля по математике и информатике.


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

1793 — американец Эли Уитни запатентовал хлопкоочистительную машину.

1944 — экспериментальная ракета MW 18014 V-2 достигает высоты 176 км, став первым искусственным объектом, достигшим космического пространства.


#Biography #Birth_Date #Events #20июня
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Ребят продолжаю набор желающих обучиться Java. 🤓

Офферов конечно не обещаю, но до твердого мидла доведу.

Пишите в лс @Oleborn ✌️
Please open Telegram to view this post
VIEW IN TELEGRAM
Скоро....

Ждете? 😉
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥14
История технологии сегодня — 21 июня

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

Ю́рий Васи́льевич Кондратю́к (настоящее имя — Алекса́ндр Игна́тьевич Шарге́й; 9 [21] июня 1897, Полтава, Полтавская губерния, Российская империя — 25 февраля 1942, Орловская область, СССР) — советский инженер, один из основоположников космонавтики. В начале XX века рассчитал оптимальную траекторию полёта к Луне. Эти расчёты были повторно переоткрыты НАСА в лунной программе «Аполлон». Предложенная в 1916 году Шаргеем траектория была впоследствии названа «трассой Кондратюка».

Симео́н Дени́ Пуассо́н (фр. Siméon Denis Poisson; 21 июня 1781, Питивье, Франция — 25 апреля 1840, Со, Франция) — французский математикмеханик и физик. Число учёных трудов Пуассона превосходит 300. Они относятся к разным областям чистой математикиматематической физикитеоретической и небесной механики.


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

1956 — в СССР принята на вооружение ракета Р-5М — первая советская ракета с ядерным боевым зарядом.

2006 — спутники Плутона получили названия Никта и Гидра.


#Biography #Birth_Date #Events #21июня
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Как заставить себя учиться 🤓

Особенно когда тебе за 30...

Казалось бы - что может быть проще? Бери источник информации и изучай что-то новое. Но оказалось, что не все так просто...


🤬С чем придется столкнуться:

Постоянные дела и банальная усталость с основной работы (да и лень немножко, конечно 🏝).

Это хорошо, когда ты молод и у тебя нет обязанностей перед семьей и окружающими. Ты волен посвятить обучению все свое свободное время...
А нам, 30+ -летним "вкатунам", которые вынуждены ежедневно бороться с окружающими проблемами, кажется сложным найти время, чтобы сесть и посмотреть (и воспринять!) видео с какой-то новой концепцией.

А постоянное обучение - вообще какая-то дикость.☠️

Кружащие заблуждения 🤔

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

Кроме того, обычное заблуждение моего круга - что после окончания школы/института, простой человек (а не какой-то там гений или вундеркинд) теряет способности к обучению, и с трудом воспринимает новую, в том числе и сложную информацию. (Не буду скрывать, и я относился к тем людям, кто распространял это заблуждение... ☺️)

Ощущение своей непроходимой тупости
🤪

Не покидает и спустя несколько лет. 🤣

А если серьезно, то чем больше ты погружаешься в программирование, тем глубже кажется кроличья нора. Новые фреймворки, библиотеки, технологии, нюансы, надстройки и костыли, кажутся дремучим лесом, в котором так легко потеряться.
А периодическое стуканье головы об что-то твердое и последующее (возможно не связанное с этим процессом), озарение, со словами "Ах, б🤬, так вот оно что!", преследует меня до сих пор (ведь обучение тут не заканчивается никогда!🤫).


Ниже дам несколько советов, которые помогли мне (и может помогут и Вам 😎)

1. Смог он, смогу и я.
Возможно Вы слышали выражение - "не боги горшки обжигают". Верьте в свои силы, даже если кажется, что это полный идиотизм.

Ведь, если смотря на человека который рассказывает об устройстве сложной системы, Вы задаетесь вопросом "Как он смог это понять?", задайте вопрос и себе "А чем я хуже?".

Бороться и не сдаваться несмотря на все возникающие препятствия сложно. И в обучении это имеет сокровенный смысл. Понимание того, что успешный программист с зп 500к+, не родился с клавиатурой во рту, а так же как и Вы возможно учился по тому же каналу в ютубе, только несколько раньше, максимально мотивирует достичь его успехов.

2. Выбрать время для обучения (и желательно много).
Скажем так, я не смог обучаться параллельно с работой. Ну никак. Поэтому воспользовавшись накоплениями, и освободившимся после увольнения временем, я все силы бросил на учебу.

И не значит, что это ваш рецепт, ведь мы все разные. Возможно вам комфортно вялотекущее обучение и устройство в IT у вас в далекой перспективе. 🙃

3. Структурируйте процесс обучения.
Сейчас в интернете гигантское количество обучающего материала. В том числе и бесплатного (да-да, это я про наш канал☺️) .
Выберите какой Вам нравится и начинайте учить от простого к сложному. Вычлените в приоритет те части, которые являются основой выбранного Вами рабочего стека и бросьте все силы туда. Иначе можно увязнуть в объеме информации или начать учить то, что Вам никогда не пригодится.

4. Вознаграждайте свое подсознание за успехи
Звучит глупо и странно, знаю. Но мотивировать себя станет в разы легче. Небольшой бонус: чашка любимого кофе, эпизод сериала или пятнадцать минут в соцсетях. Мозг любит вознаграждения, и это ещё один повод не бросить начатое.

5. Чёткая цель и никаких «зачем» после начала.
Наверно моя основная мотивация в ежедневной учебе. А может я просто упрямый 🐏 😄.
Поставьте себе глобально - максимально - реально достижимую цель. Продумайте шаги и ступени до нее, разбив на мелкие подцели и достигая их, начинайте путь к следующей. И не успеете оглянуться как половина пути будет пройдена. А может и весь)))

😎
#motivation
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥5👍31
🤓6
🤓4🤣2
История технологии сегодня — 22 июня

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

Доктор Ко́нрад Эрнст О́тто Цу́зе (нем. Dr. Konrad Ernst Otto Zuse; 22 июня 1910, Берлин, Германская империя — 18 декабря 1995, Хюнфельд, Германия) — немецкий инженер, один из пионеров компьютеростроения. Наиболее известен как создатель первого действительно работающего электро-механического программируемого компьютера Z3 (1941) и первого языка программирования высокого уровня Планкалькюль (1948).

Гео́ргий (Ю́рий) Ви́кторович Вульф (22 июня 1863, Нежин, Российская Империя — 25 декабря 1925, Москва, СССР) — российский учёный-кристаллограф, автор «сетки Вульфа» и формулы Брэгга — Вульфа. Автор более 150 работ по кристаллографии, кристаллофизике, кристаллооптике, рентгеноструктурному анализу, минералогии.

Ге́рман Минко́вский (нем. Hermann Minkowski; 22 июня 1864, Алексоты, Августовская губерния, Мариампольский уезд, Российская империя — 12 января 1909, Гёттинген, Германская империя) — немецкий математик, разработавший геометрическую теорию чисел и геометрическую четырёхмерную модель теории относительности. Первые результаты Минковского касались теории квадратичных форм. В 1896 году опубликован результат, ныне известный как теорема Минковского о выпуклом теле — о том, что выпуклая область n-мерного пространства, объёмом >=2n и симметричная относительно начала координат, непременно содержит точку с целочисленными координатами, отличную от начала координат. По словам Касселса[17], вся геометрия чисел основана на этом результате. После создания геометрии чисел Минковский много и плодотворно работает над применением полученных результатов в других областях теории чисел: диофантовы приближения, теория многогранников и другие. Ему принадлежат фундаментальные достижения в геометрии выпуклых тел. В 1907 году Минковский предложил геометрическое представление кинематики теории относительности, введя четырёхмерное псевдоевклидово пространство (известное сейчас как пространство Минковского). В этой модели время и пространство представляют собой не различные сущности, а взаимосвязанные измерения единого пространства-времени. Все релятивистские эффекты получили наглядное геометрическое истолкование.


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

1978 — обнаружен спутник Плутона — Харон.


#Biography #Birth_Date #Events #22июня
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
[Совет по Java #052]

Тема: Stream.iterate(seed, predicate, unaryOperator) в Java 9 позволяет создавать ограниченные стримы без явного вызова limit().

Проблема: В Java 8 метод Stream.iterate(seed, unaryOperator) генерирует бесконечный стрим, который требует явного ограничения через limit(). Это неудобно, когда условие завершения зависит от самих значений, а не от количества элементов.

Разработчики часто используют limit с заранее неизвестным числом итераций или добавляют takeWhile (Java 9), что может быть избыточно. В Java 9 появилась перегрузка iterate(seed, predicate, unaryOperator), которая позволяет задать условие продолжения. Однако важно понимать: predicate проверяется до применения unaryOperator к текущему элементу, а не после. Это значит, что если первый элемент не удовлетворяет предикату, стрим будет пустым, а не выдаст его и остановится. Ошибка в логике может привести к неожиданному пропуску элементов или бесконечному циклу, если предикат всегда true.

Решение: Используйте Stream.iterate с предикатом для компактного создания конечных последовательностей, когда условие зависит от значения элемента. Убедитесь, что предикат правильно определяет момент остановки: он проверяется перед каждой итерацией, начиная с начального значения. Если предикат возвращает false для начального элемента, стрим не сгенерирует ни одного элемента. Для условий, которые зависят от текущего элемента (например, пока число меньше 100), это работает корректно.
public class StreamIteratePredicate {

public static void main(String[] args) {
//Java 8: бесконечный стрим + limit
Stream.iterate(1, i -> i * 2)
.limit(5)
.forEach(System.out::println); // 1, 2, 4, 8, 16

//Java 9: ограниченный стрим через predicate (проверка ДО генерации)
Stream.iterate(1, i -> i <= 16, i -> i * 2)
.forEach(System.out::println); // 1, 2, 4, 8, 16 (включает 16, т.к. проверка на 16 == true)

// Внимание: если начальное значение не удовлетворяет предикату — стрим пуст
Stream.iterate(100, i -> i <= 16, i -> i / 2)
.forEach(System.out::println); // Нет вывода!

//Опасный пример: предикат всегда true — бесконечный стрим (без limit)
// Stream.iterate(1, i -> true, i -> i + 1).forEach(...) // зависнет

//Альтернатива с takeWhile (Java 9) — условие проверяется ПОСЛЕ генерации
Stream.iterate(1, i -> i * 2)
.takeWhile(i -> i <= 16)
.forEach(System.out::println); // 1, 2, 4, 8, 16

// Разница: если нужно включить элемент, который не удовлетворяет условию — takeWhile подходит
// Например, генерация чисел до первого, превышающего 5
Stream.iterate(1, i -> i + 1)
.takeWhile(i -> i <= 5)
.forEach(System.out::println); // 1,2,3,4,5 (включает 5)

// Но с iterate с predicate: если i = 6, то предикат i <= 5 даст false до генерации 6, поэтому 5 включена
Stream.iterate(1, i -> i <= 5, i -> i + 1)
.forEach(System.out::println); // 1,2,3,4,5 — то же самое
}
}


Объяснение:
 Метод Stream.iterate(seed, predicate, unaryOperator) работает по следующему алгоритму: сначала проверяет predicate.test(seed). Если false, стрим завершается. Если true, выдает seed как первый элемент.

Затем для каждого следующего элемента применяется unaryOperator к предыдущему, и перед выдачей проверяется predicate.test(next). Таким образом, предикат определяет, должен ли следующий элемент быть включен. Это отличается от takeWhile, который проверяет условие на текущем элементе и включает его, даже если следующее нарушит условие. Выбор между ними зависит от семантики: если условие завершения относится к самому значению (например, "пока значение меньше 100"), то iterate с предикатом и takeWhile дадут одинаковый результат для корректных данных. Но если начальное значение не соответствует условию, iterate выдаст пустой стрим, а takeWhile — тоже пустой, потому что первый элемент не проходит. В сложных сценариях, где нужно включить элемент, нарушающий условие, используйте takeWhile или ручной контроль.

#Java #советы
👍3
15. Saga Choreography: от HTTP к Event-Driven архитектуре

В этом видео мы делаем первый по-настоящему архитектурный шаг в серии OrderHub: заменяем синхронный HTTP-вызов между микросервисами на асинхронную Saga Choreography.

До этого видео мы уже настроили Kafka, Outbox, Debezium и OpenTelemetry, но самая важная бизнес-операция – оплата заказа – всё ещё выполнялась синхронно: клиент ждал ответа от payment-service, а при его отказе заказ не создавался.

Мы исправляем это:
🔵 Убираем блокирующий HTTP-вызов из OrderService
🔵 Вводим новый статус AWAITING_PAYMENT
🔵 Превращаем payment-service в полноценного участника Saga (Kafka consumer + producer)
🔵 Добавляем PaymentEventConsumer в order-service, который обрабатывает PaymentCompletedEvent и PaymentFailedEvent
🔵 Реализуем компенсирующую транзакцию (cancelOrder) – вместо rollback делаем новое действие


Что вы узнаете
🔵 Почему синхронный HTTP – это антипаттерн в микросервисах
🔵 Что такое Saga Choreography и чем она отличается от Orchestration
🔵 Как перейти от ACID к BASE и от rollback к компенсации
🔵 Как сделать бизнес-операцию асинхронной с помощью Kafka и Outbox
🔵 Как реализовать компенсирующую транзакцию на практике

Исходный код проекта на GitHub наверняка заслуживает Ваших звезд! 🙂

Ссылка на Youtube
Ссылка на Рутьюб

Смотрите, ставьте лайки, подписывайтесь на каналы!✌️

Жду ваших реакций и оценок
🙂
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7
Что выведет код?

import java.util.stream.Stream;

public class Task220626 {
public static void main(String[] args) {
Stream.iterate(1, i -> i <= 3, i -> i + 1)
.peek(System.out::print)
.anyMatch(i -> i > 1);
}
}


#Tasks
👍2
Варианты ответа:
Anonymous Quiz
42%
123
25%
23
25%
12
8%
1
👍2
💯 не робот ответил, я уверен!
Please open Telegram to view this post
VIEW IN TELEGRAM
🤣11🤯1
Что такое boolean в Java? Сколько значений он может принимать? 🤓

Ответ:

boolean
 — примитивный тип, принимающий два значения: true и false.

Размер в памяти явно не специфицирован (зависит от JVM, обычно 1 байт, но в массивах — 1 байт на элемент, а в стеке может быть 4 байта).

Не является числовым типом — не может быть преобразован в int или наоборот (в отличие от C/C++).

Используется в условных выражениях (if, while), логических операторах (&&, ||, !) и для хранения флагов.



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

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

А́лан Мэ́тисон Тью́ринг (англ. Alan Mathison Turing [ˈtjʊərɪŋ]; 23 июня 1912, Вестминстер — 7 июня 1954, Чешир) — британский математиклогик и криптограф, оказавший существенное влияние на развитие информатики. Офицер ордена Британской империи (OBE, 1945), член Лондонского королевского общества (1951). Предложенная им в 1936 году абстрактная вычислительная «Машина Тьюринга», которую можно считать моделью компьютера общего назначения, позволила формализовать понятие алгоритма и до сих пор используется во множестве теоретических и практических исследований. Научные труды А. Тьюринга — общепризнанный вклад в основания информатики (и в частности — теории искусственного интеллекта).


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

1868 — Кристофер Лэтем Шоулз из Висконсина запатентовал пишущую машинку. Размерами она была с большой стол, клавиатура её напоминала рояль, печатала машинка только большими буквами, причём машинистка не видела результата своей работы, поскольку бумага находилась под планшетом.

1991 — выпущена видеоигра Sonic the Hedgehog для платформы Sega Mega Drive (первая игра этой серии).


#Biography #Birth_Date #Events #23июня
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Раздел 11. Работа с файлами, I/O и сетью (NIO.2)

Глава 1. Классический Java I/O (java.io)

BufferedReader – построчное чтение. Путь данных и управление памятью

BufferedReader — декоратор над Reader, добавляющий буферизацию символьного ввода и специализированные методы для построчного чтения. В отличие от базового Reader, который оперирует массивами char[], BufferedReader предоставляет readLine() — метод, возвращающий строку текста, завершающуюся символом перевода строки.

Ключевое архитектурное решение — разделение между транспортом и семантикой. InputStreamReader декодирует байты в символы. BufferedReader накапливает символы в буфере и распознает логические строки, абстрагируя приложение от деталей разделителей строк (\n, \r, \r\n).

Внутреннее устройство
// Упрощенная структура из OpenJDK
public class BufferedReader extends Reader {
// Буфер символов в heap JVM
private char[] cb;

// Количество символов в буфере
private int nChars;

// Текущая позиция чтения
private int nextChar;

// Маркер для mark/reset
private int markedChar = UNMARKED;
private int readAheadLimit = 0;

// Признак пропуска \n после \r
private boolean skipLF = false;

// Конструкторы
public BufferedReader(Reader in) {
this(in, defaultCharBufferSize); // 8192 по умолчанию
}

public BufferedReader(Reader in, int sz) {
super(in);
if (sz <= 0)
throw new IllegalArgumentException("Buffer size <= 0");
cb = new char[sz]; // Выделение в heap
}
}

Поле cb — массив char[] в heap, служащий кольцевым буфером для накопления символов из underlying Reader. Размер по умолчанию 8192 символов, что соответствует 16 KB памяти heap (каждый char — 2 байта).


Механика readLine()

readLine() выполняет последовательный поиск символов перевода строки в буфере, накапливая символы до разделителя во временный StringBuilder, и создает String при нахождении \n или \r\n:
// Упрощенная логика readLine()
public String readLine() throws IOException {
StringBuilder sb = new StringBuilder(defaultExpectedLineLength);

while (true) {
if (nextChar >= nChars) {
fill(); // Заполнение буфера из underlying Reader
if (nextChar >= nChars) {
// Конец потока
return sb.length() > 0 ? sb.toString() : null;
}
}

char c = cb[nextChar++];

if (c == '\n') {
if (skipLF) {
skipLF = false;
continue; // Пропуск \n после \r
}
return sb.toString(); // Строка завершена
}

if (c == '\r') {
skipLF = true;
return sb.toString(); // Строка завершена, \n будет пропущен
}

sb.append(c); // Накопление символов
}
}


Ключевые особенности:
Универсальность разделителей. \n (Unix), \r (старый Mac), \r\n (Windows) распознаются корректно.
Разделитель не включается в результат. Возвращенная String не содержит \n или \r.
Признак конца потока. null возвращается, когда достигнут EOF и StringBuilder пуст.

Путь данных в памяти
[Диск: файл в байтах UTF-8]
-> [Page Cache ОС]
-> [FileInputStream: системный вызов read()]
-> [InputStreamReader: декодирование байт -> char]
-> [BufferedReader.fill(): копирование char[] в cb[8192]]
-> [BufferedReader.readLine(): поиск \n в cb]
-> [StringBuilder: накопление символов строки]
-> [StringBuilder.toString(): создание String в heap]
-> [Возврат String]



Жизненный цикл объектов в heap

При каждом вызове readLine() создаются объекты:
StringBuilder — временный накопитель символов. Создается при каждом вызове readLine(), живет до возврата String. Собирается GC немедленно.
String — результат. Создается через StringBuilder.toString(). В современных JDK (9+) String хранит byte[] вместо char[], с компактным представлением для латиницы (1 байт на символ) и UTF-16 для остального.

Внутренний массив StringBuilderchar[], расширяющийся при необходимости. При превышении емкости создается новый массив большего размера с System.arraycopy.
// Длинная строка превышает начальную емкость StringBuilder
StringBuilder sb = new StringBuilder(80); // Начальный массив char[80]
// Строка длиной 200 символов
// sb расширяется: char[80] -> char[160] -> char[320] -> ...
// Старые массивы становятся мусором

Это создает дополнительное давление на GC для файлов с очень длинными строками.


Роль garbage collector

Сценарий: чтение файла с миллионом строк
public long countLines(String path) throws IOException {
long lineCount = 0;

try (BufferedReader reader = new BufferedReader(
new InputStreamReader(
new FileInputStream(path), StandardCharsets.UTF_8))) {

String line;
while ((line = reader.readLine()) != null) {
lineCount++;
// line — новая String в heap
// StringBuilder и его внутренний char[] — мусор
}

} // reader закрыт, cb освобожден

return lineCount;
}


Память в процессе:

cb[8192] — буфер BufferedReader, живет до закрытия
StringBuilder + внутренний char[] — при каждом вызове readLine()
String — при каждом вызове readLine(), возвращается вызывающему

Если вызывающий код не сохраняет String, она становится мусором после итерации. Для файла с 1 000 000 строк создается 1 000 000 объектов String + 1 000 000 StringBuilder + несколько расширенных char[] для длинных строк. Все они короткоживущие и собираются minor GC в young generation.

Проблема: сохранение всех строк
// Антипаттерн: удержание всех строк в памяти
public List<String> readAllLines(String path) throws IOException {
List<String> lines = new ArrayList<>();

try (BufferedReader reader = new BufferedReader(
new InputStreamReader(new FileInputStream(path), StandardCharsets.UTF_8))) {

String line;
while ((line = reader.readLine()) != null) {
lines.add(line); // Все String удерживаются списком
}
}

return lines; // Возврат: все строки в heap
}

Здесь все String удерживаются списком lines. Для файла 100MB с ~1 000 000 строк это ~100MB в String + оверхед ArrayList. GC не может собрать эти String, пока список достижим. Это приводит к увеличению old generation и потенциальному OutOfMemoryError.

Решение — потоковая обработка без накопления:
// Правильно: потоковая обработка без хранения всех строк
public void processLines(String path, Consumer<String> processor) throws IOException {
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(new FileInputStream(path), StandardCharsets.UTF_8))) {

String line;
while ((line = reader.readLine()) != null) {
processor.accept(line);
// line становится недостижимой после итерации, если processor не сохраняет
}
}
}



#Java #для_новичков #beginner #IO #NIO #BufferedReader
👍4