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

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

Наш канал на RUTube - https://rutube.ru/channel/37896292/
Download Telegram
Как объявить константу в Java?🤓

Ответ:

Константа в Java
— это переменная, значение которой нельзя изменить.

Объявляется с ключевыми словами static final. Принято имя писать заглавными буквами с подчеркиваниями: public static final double PI = 3.14159;. final означает, что ссылку нельзя переназначить (для примитивов — значение, для объектов — ссылку, но сам объект может быть изменяем).

Для неизменяемых объектов (например, String, LocalDate) final вместе с неизменяемостью даёт полную константу.


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

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

Никола́й Серге́евич Бахва́лов (29 мая 1934, Москва — 29 августа 2005, Москва) — советский и российский математик, специалист по вычислительной математикеАкадемик РАН (1991), заслуженный деятель науки Российской Федерации (1994). Вычислительная и прикладная математикачисленные методы, оптимизация алгоритмов, теория функций, математические проблемы механики неоднородных сред, в частности композитных материалов, задачи волновой физики, теория осреднения процессов в периодических средах (Государственная премия 1985 г.), многосеточные методы решения уравнений эллиптического типа (Государственная премия 2003 г.).

Пи́тер Уэр Хиггс (англ. Peter Ware Higgs; 29 мая 1929, Ньюкасл-апон-Тайн, Нортамберленд — 8 апреля 2024, Эдинбург) — британский физик-теоретик, профессор Эдинбургского университета. Лауреат Нобелевской премии по физике (2013) за предсказание бозона Хиггса. Прославился благодаря предложенному им в 1960-х годах механизму спонтанного нарушения электрослабой симметрии, объясняющему происхождение массы элементарных частиц и, в частности, масс векторных W- и Z-бозонов. Это открытие он сделал во время горной прогулки в районе Эдинбурга; вернувшись после неё в лабораторию, Хиггс заявил, что у него возникла «грандиозная идея». Механизм, носящий его фамилию, предсказывает существование новой частицы, хиггсовского бозона. Об открытии частицы было объявлено 4 июля 2012 года на пресс-конференции ЦЕРНа (сам Хиггс заявил по этому поводу, что не ожидал экспериментального подтверждения собственной теории при своей жизни). Открытие бозона Хиггса признано научным прорывом 2012 года. Ныне механизм Хиггса считается одним из основных компонентов Стандартной модели.

Алексе́й Миха́йлович Черёмухин (1895—1958) — советский авиационный конструктор, создатель первого советского вертолёта. Доктор технических наук (1937), профессор (1934). Заслуженный деятель науки и техники РСФСР. Лауреат Ленинской премии.


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

1802 — физик и основоположник электрометаллургии академик В. В. Петров открыл явление электрической дуги.

1975 — на Белорусском автозаводе начато производство крупнейшего в СССР грузовика — «БелАЗ-7520».



#Biography #Birth_Date #Events #29мая
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
[Совет по Java #043]

Тема: java.lang.Number — абстрактный класс, нельзя создать экземпляр.

Проблема: Некоторые разработчики ошибочно полагают, что раз Number является абстрактным, то нельзя использовать его в полиморфном контексте или что методы вроде doubleValue() не будут работать для конкретных типов.

Другие, наоборот, пытаются создать экземпляр new Number() (что приводит к ошибке компиляции) или ожидают, что Number можно использовать как универсальный контейнер для любых чисел без потери точности. Также существует непонимание того, что Number не является супертипом для примитивов (int не является Number), а только для их оберток.

Решение: Используйте Number как полиморфный тип для методов, которые должны принимать любые числовые обертки (IntegerDoubleLongFloatShortByteBigIntegerBigDecimal). Для получения числового значения вызывайте соответствующий метод: doubleValue()intValue()longValue() и т.д. Помните, что эти методы могут привести к потере точности (например, Double -> intValue()).

Для работы с неизвестным числовым типом используйте doubleValue() как наиболее универсальный (самый широкий диапазон). Если нужна точность, проверяйте тип через instanceof. Не создавайте Number напрямую.
public class NumberPolymorphism {

//Полиморфный метод, принимающий любой числовой тип
public static double square(Number num) {
double d = num.doubleValue();
return d * d;
}

//С проверкой типа для сохранения точности
public static Number add(Number a, Number b) {
// Для точных вычислений нужно знать тип
if (a instanceof Integer && b instanceof Integer) {
return a.intValue() + b.intValue();
}
if (a instanceof Double || b instanceof Double) {
return a.doubleValue() + b.doubleValue();
}
if (a instanceof BigDecimal || b instanceof BigDecimal) {
return toBigDecimal(a).add(toBigDecimal(b));
}
return a.doubleValue() + b.doubleValue();
}

private static BigDecimal toBigDecimal(Number n) {
if (n instanceof BigDecimal) return (BigDecimal) n;
return BigDecimal.valueOf(n.doubleValue());
}

//Ошибка: Number абстрактный
// Number n = new Number(); // не компилируется

//Правильно: создаем конкретные типы
Number intNum = 42; // autoboxing -> Integer
Number doubleNum = 3.14; // autoboxing -> Double
Number longNum = 100L; // autoboxing -> Long
Number bigDec = new BigDecimal("123.45");

//Демонстрация полиморфизма
public static void main(String[] args) {
List<Number> numbers = Arrays.asList(10, 3.14, 100L, new BigDecimal("99.99"));

// Полиморфная обработка
for (Number n : numbers) {
System.out.println("Value: " + n);
System.out.println(" int: " + n.intValue());
System.out.println(" double: " + n.doubleValue());
System.out.println(" square: " + square(n));
}

//Потеря точности при преобразовании
Double precise = 123.456;
Number asNumber = precise;
int truncated = asNumber.intValue(); // 123 — потеряна дробная часть
System.out.println("Truncated: " + truncated);
}
}


Объяснение:
 Number — абстрактный класс, являющийся супертипом для всех числовых оберток в Java.

Он объявляет абстрактные методы intValue()longValue()floatValue()doubleValue(), которые реализуются в каждом конкретном классе-наследнике. Полиморфизм работает стандартным образом: переменная типа Number может ссылаться на любой объект подкласса. При вызове, например, doubleValue() JVM динамически выбирает реализацию в соответствии с фактическим типом объекта. Важно помнить, что примитивные типы (intdouble) не являются подтипами Number, но при автоупаковке они преобразуются в соответствующие обертки (IntegerDouble).


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

import java.util.ArrayList;
import java.util.List;

public class Task290526 {
public static void main(String[] args) {
List<Number> numbers = new ArrayList<>();
numbers.add(10);
numbers.add(5.5);
numbers.add(3);
numbers.add(2L);

Number sum = numbers.get(0).intValue() + numbers.get(1).doubleValue();
System.out.println(sum.getClass().getSimpleName());

Number product = numbers.get(2).longValue() * numbers.get(3).longValue();
System.out.println(product.getClass().getSimpleName());
}
}



#Tasks
👍4
👍4
Что такое transient? Где применяется?🤓

Ответ:

transient
 — модификатор поля, указывающий, что это поле не должно участвовать в сериализации.

При десериализации такое поле получает значение по умолчанию (для объектов — null, для примитивов — 0, false, '\u0000').

Применяется для полей, которые:
1) являются производными (можно вычислить из других полей).
2) содержат конфиденциальную информацию (пароли, ключи).
3) не сериализуемы (например, Thread, Socket, FileInputStream).

Используется для уменьшения размера сериализованных данных и повышения безопасности.


#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7
Всем доброго утра! 🏃

Не забываем заботиться о здоровье, ударники сидячего труда💪🫡🤣
👍5
История технологии сегодня — 30 мая

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

Алексе́й Архи́пович Лео́нов (30 мая 1934ЛиствянкаЗападно-Сибирский край — 11 октября 2019Басманный районМосква) — лётчик-космонавт СССР № 11, первый человек в мире, вышедший в открытый космос. 18—19 марта 1965 года совместно с Павлом Беляевым совершил полёт в космос в качестве второго пилота на космическом корабле «Восход-2». В ходе полёта осуществил первый в истории космонавтики выход в открытый космос, проявив при этом исключительное мужество, особенно в нештатной ситуации, когда раздувшийся космический скафандр препятствовал его возвращению в космический корабль.
(от меня - великий человек, я встречался с ним лично, здоровался за руку).

Ха́ннес У́лоф Йёста Альве́н (Альфвен) (швед. Hannes Olof Gösta Alfvén; 30 мая 1908, Норрчёпинг — 2 апреля 1995, Юрсхольм) — шведский физик, специалист по физике плазмы, лауреат Нобелевской премии по физике в 1970 году за работы в области теории магнитогидродинамики. Внёс существенный вклад в физику плазмы, включая такие направления, как теории северного сияниярадиационных поясов Ван Аллена, эффект геомагнитных бурь на магнитное поле Землимагнитосферы, в проблемы формирования хвостов комет и солнечной системы, динамики плазмы в галактике (плазменная космология).


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

1900 — на Всемирной выставке в Париже датский инженер Вальдемар Поульсен представил изобретённый им прибор — телеграфон. По сути, это была магнитная лента для звукозаписи.


#Biography #Birth_Date #Events #30мая
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
С 23.05 по 29.05
Предыдущий пост(с 09.05 по 22.05)

Запись встреч/видео:
В разработке


Обучающие статьи:

[Совет по Java #041]
Тема: Integer кэширует значения от -128 до 127.

[Совет по Java #042]
Тема: Comparator.comparing(Function) требует, чтобы ключ сравнения был Comparable.

[Совет по Java #043]
Тема: java.lang.Number — абстрактный класс, нельзя создать экземпляр.

Раздел 9. Исключения, логирование, отладка

Глава 2. Логирование (Logging)
MDC (Mapped Diagnostic Context) – привязка контекстной информации к логам
Логирование в «Библиотеке»

Полезные статьи и видео:
Как мы ускорили расчёт факторов ранжирования в поиске Ozon с помощью динамической компиляции

Как и всегда, задачи можно найти под тегом - #Tasks, вопросы с собеседований - #собеседование
👍3
This media is not supported in your browser
VIEW IN TELEGRAM
О как точно подмечено 😂
🆒3
История технологии сегодня — 31 мая

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

Евгений Павлович Тверитинов (19 [31] мая 1850, Кронштадт, Санкт-Петербургская губерния — 3 апреля 1920, Кронштадт, Петроградская губерния) — офицер Российского императорского флота, первый русский флотский электрик, специалист по минной и корабельной электротехнике, изобретатель и создатель нового типа электрического аккумулятора. Впервые в России оборудовал боевые корабли установками электрического освещения, организовал электрическую иллюминацию Кремля и колокольни Ивана Великого при коронации императора Александра III и его супруги.

Джей Глен Майнер (англ. Jay Glenn Miner, также Джей Майнер; 31 мая 1932 года — 20 июня 1994 года)знаменитый разработчик микросхем, известный прежде всего как человек, благодаря которому стало возможным воплощение концепций, позднее получивших название мультимедиа. Основной разработчик первого в мире мультимедийного персонального компьютера Amiga 1000 (1985 год). Взгляды Джея Майнера настолько опережали время, что сегодня он воспринимается многими как провидец, который, прежде всего, сам внёс посильную лепту в осуществление своей мечты.

Джон Роберт Шри́ффер (англ. John Robert Schrieffer; 31 мая 1931, Ок-Парк, Иллинойс, США — 27 июля 2019) — американский физик, лауреат Нобелевской премии по физике (1972, совместно с Джоном Бардином и Леоном Н. Купером) за создание БКШ-теории, названной по их инициалам. В 1956 году Шриффер, Бардин и Купер разработали теорию сверхпроводимости кристаллических твёрдых тел, основанную на представлении о сверхтекучести куперовских пар электронов.


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

1946 — образовано самолётостроительное ОКБ О. К. Антонова.


#Biography #Birth_Date #Events #31мая
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
История технологии сегодня — 1 июня

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

Ма́ркус Алексе́й Пе́рссон (швед. Markus Alexej Persson [ˈmǎrkɵs ˈpæ̌ːʂɔn] о файле, также известный под никнеймом Notch; род. 1 июня 1979, Стокгольм, Швеция) — шведский программист и геймдизайнер, бывший владелец компании Mojang Studios. Является создателем популярной компьютерной игры Minecraft. Самый популярный проект Перссона — компьютерная игра в жанре песочницы с элементами симулятора выживания и открытым миром Minecraft, выпущенная 18 ноября 2011 года. Ради работы над игрой Перссон уволился с поста гейм-дизайнера. В начале 2011 года Mojang AB продала первый миллион копий игры, через несколько месяцев — второй и через ещё несколько месяцев — третий. Mojang наняла нескольких разработчиков в команду Minecraft после того, как Перссон передал пост главного разработчика Йенсу Бергенстену (jeb_). Игра была адаптирована под iOS и Android. Версия для Xbox появилась 9 мая 2012 года и включает несколько нововведений, например, возможность обучения и несколько текстур-паков и скинов. После продажи Mojang Microsoft за 2,5 миллиарда долларов Перссон прекратил работу над проектом, а его место занял программист Йенс Бергенстен.

Эдвард Чарльз Титчмарш (англ. Edward Charles Titchmarsh, 1 июня 1899, Ньюбери, Беркшир, Англия, Великобритания — 18 января 1963, Оксфорд, Оксфордшир, Англия, Великобритания) — английский математик, специалист по математическому анализу и аналитической теории чисел. Написал около 130 статей по математике, а также пять монографий, один учебник («Теория функций») и одну популярную книгу. Его работы были посвящены рядам Фурьеинтегралам Фурьецелым функцияминтегральным уравнениямдифференциальным уравнениям второго порядка, исследованию свойств дзета-функции Римана, а также другим математическим проблемам.


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

1936 — открылась первая в СССР трансконтинентальная авиалиния из Москвы во Владивосток. В те времена перелёты совершались с промежуточными посадками — за 4 суток.


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

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

Байтовые потоки: абстрактные классы InputStream и OutputStream

Байтовые потоки в Java представляют собой фундаментальный слой абстракции для работы с данными в их сыром, двоичном виде. Классы InputStream и OutputStream оперируют единицей данных размером в 8 бит — байтом — и не накладывают никакой семантической интерпретации на прочитанные или записанные значения. Байт может быть частью изображения JPEG, аудиофрейма MP3, сериализованного объекта, зашифрованного пакета или любого другого бинарного формата.

Это разделение ответственности — транспорт без интерпретации — является ключевым архитектурным решением Java I/O. Байтовые потоки отвечают только за перемещение сырых данных между источником и назначением. Интерпретация этих данных — декодирование текста, парсинг изображений, десериализация объектов — возлагается на более высокие уровни абстракции, которые строятся поверх байтовых потоков через паттерн декоратора.

Использование байтовых потоков обязательно для любых бинарных форматов, где побитовая точность критична. Попытка чтения бинарного файла через символьные потоки (Reader/Writer) приведет к повреждению данных, так как символьные потоки применяют кодировку, трансформирующую последовательности байт в Unicode-символы. Для форматов вроде PNG, PDF, ZIP, MP4 или собственных бинарных протоколов единственно корректный выбор — байтовые потоки.

Путь данных в памяти JVM: от диска до heap

Когда FileInputStream.read() читает байт из файла, данные проходят через несколько уровней памяти прежде чем стать доступными Java-коду. Этот путь критичен для понимания производительности и поведения garbage collector.

Уровень 1: Диск и страничный кэш ОС. Файловая система читает данные с блочного устройства в страничный кэш ядра (page cache). Это память ядра операционной системы, недоступная напрямую из Java. Размер страницы обычно 4KB, и чтение меньшего объема все равно загружает целую страницу.

Уровень 2: Нативный буфер и системный вызов. JVM выполняет системный вызов read(), который копирует данные из страничного кэша ядра в нативный буфер в userspace. Это прямое копирование между kernel space и user space управляется DMA (Direct Memory Access) контроллером без участия CPU для самих данных, но требует переключения контекста процессора из userspace в kernelspace.

Уровень 3: Копирование в heap JVM. Данные из нативного буфера копируются в массив byte[], расположенный в heap JVM. Это вторая копия данных, и именно здесь начинает работать garbage collector.
// read() возвращает int, но данные прошли путь: диск -> page cache -> нативный буфер -> heap
int byteValue = fileInputStream.read();

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


Буферизация и сокращение пути данных

BufferedInputStream решает проблему, вводя промежуточный буфер в heap JVM:
// BufferedInputStream внутренне содержит byte[] buf размером по умолчанию 8192 байт
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream("data.bin"))) {
int b;
while ((b = bis.read()) != -1) {
processByte(b);
}
}

При первом вызове read() BufferedInputStream читает до 8192 байт из underlying потока одним системным вызовом, заполняя внутренний массив buf. Последующие вызовы read() извлекают байты из этого массива без системных вызовов. Данные в buf — это обычный массив в heap, управляемый garbage collector.

Путь данных с буферизацией:

Первый read(): диск -> page cache -> нативный буфер -> buf[8192] в heap -> возврат buf[0]
Второй read(): buf[1] из heap (системный вызов отсутствует)
После исчерпания buf: повторение шага 1
Это сокращает количество системных вызовов с N до N/8192, где N — размер файла.


#Java #для_новичков #beginner #IO #NIO #InputStream #OutputStream
👍5
Роль garbage collector

Массив byte[], используемый как буфер, является обычным объектом в heap JVM.

Его жизненный цикл определяется ссылками:

Внутренний буфер BufferedInputStream удерживается ссылкой из самого объекта BufferedInputStream
Объект BufferedInputStream удерживается локальной переменной в стеке потока выполнения
При выходе из блока try-with-resources вызывается close(), который обнуляет ссылку на underlying поток
Если BufferedInputStream становится недостижимым, GC помечает внутренний byte[] как мусор

Важный нюанс: при использовании BufferedInputStream внутри try-with-resources буфер освобождается предсказуемо при выходе из блока. Однако если ссылка на поток сохраняется в поле класса или передается в другие компоненты, GC не может освободить буфер до тех пор, пока объект BufferedInputStream остается достижимым. Утечки памяти в I/O-коде обычно связаны именно с забытыми ссылками на потоки, а не с самими данными.


Крупные массивы и GC-pressure

При чтении больших файлов размер буфера влияет на поведение garbage collector:
// Маленький буфер: частые системные вызовы, но быстрое освобождение GC
byte[] smallBuffer = new byte[1024];

// Большой буфер: редкие системные вызовы, но большое выделение памяти
byte[] largeBuffer = new byte[1024 * 1024]; // 1MB

Буфер в 1MB выделяется в heap как единый массив. В G1 GC массивы размером более половины размера региона (обычно > 512KB для региона 1MB) считаются humongous objects и размещаются в специальных humongous-регионах. Эти регионы освобождаются только полным циклом concurrent mark-sweep, что может увеличить паузы GC.

Для приложений с интенсивным I/O рекомендуется переиспользование буферов через пулы объектов, что устраняет накладные расходы на выделение и сборку:
// Переиспользование буфера вместо создания нового при каждой операции
private static final ThreadLocal<byte[]> BUFFER = ThreadLocal.withInitial(() -> new byte[8192]);

public void processFile(String path) throws IOException {
byte[] buffer = BUFFER.get(); // Переиспользование, не создание

try (InputStream in = new FileInputStream(path)) {
int bytesRead;
while ((bytesRead = in.read(buffer)) != -1) {
processChunk(buffer, bytesRead);
}
}
// Буфер остается в ThreadLocal, не подлежит GC между вызовами
}

Здесь буфер привязан к потоку через ThreadLocal и не создается заново при каждом вызове. Это устраняет аллокации в hot path, но требует осторожности: буфер занимает память на протяжении жизни потока, даже когда не используется.

#Java #для_новичков #beginner #IO #NIO #InputStream #OutputStream
👍2
InputStream: чтение байтов

InputStream — абстрактный класс, определяющий контракт для всех входных байтовых потоков. Его методы реализуют семантику последовательного чтения: данные извлекаются из источника в порядке FIFO, и невозможно вернуться назад без специальных механизмов (mark/reset, доступных не во всех реализациях).

int read() — читает один байт из потока. Возвращает значение в диапазоне 0-255 как int, что позволяет различать валидные байты (0-255) от признака конца потока. Когда достигнут конец потока, метод возвращает -1. Этот контракт фундаментален: -1 — единственный способ узнать, что данные в источнике исчерпаны. Возврат int вместо byte обусловлен необходимостью представления 256 возможных значений байта плюс специальное значение -1 для EOF. Тип byte в Java знаковый и имеет диапазон -128..127, что не позволил бы различить байт 0xFF (255 беззнаковый, -1 знаковый) от признака конца потока.

int read(byte[] b) — читает байты в предоставленный массив, заполняя его полностью или частично. Возвращает количество фактически прочитанных байт, или -1 при достижении конца потока. Этот метод существенно эффективнее посимвольного чтения, так как уменьшает количество системных вызовов. Однако он не гарантирует заполнение всего массива — при неполных данных возвращается меньшее количество байт, и приложение должно обработать эту ситуацию.

int read(byte[] b, int off, int len) — читает до len байт в массив b, начиная с позиции off. Возвращает количество прочитанных байт или -1. Этот метод предоставляет максимальный контроль над буферизацией.

long skip(long n)
— пропускает до n байт в потоке. Возвращает количество фактически пропущенных байт, которое может быть меньше n.

int available() — возвращает оценку количества байт, которые можно прочитать без блокирования. Для файловых потоков это обычно оставшийся размер файла, для сетевых — количество данных в сокет-буфере. Значение 0 не означает конец потока, а только отсутствие немедленно доступных данных.

void close() — закрывает поток и освобождает связанные системные ресурсы: файловые дескрипторы, сокеты, соединения с базой данных. Реализации InputStream не объявляют close() как AutoCloseable, но все конкретные подклассы реализуют этот интерфейс, что позволяет использовать try-with-resources.

void mark(int readlimit) и void reset() — поддержка маркировки позиции в потоке для последующего возврата. Доступность проверяется через boolean markSupported(). Большинство потоков, основанных на внешних ресурсах (файлы, сети), не поддерживают эту операцию.


Контракт read(): возврат -1 при конце потока

Контракт метода read() требует особого внимания. Метод блокирует выполнение до тех пор, пока не станет доступен хотя бы один байт, не произойдет IOException, или не будет достигнут конец потока. При нормальном завершении потока возвращается -1, и все последующие вызовы read() также возвращают -1.

Этот контракт определяет стандартный паттерн чтения:
// Антипаттерн: чтение байта за байтом без буферизации
public void readByteByByte(InputStream in) throws IOException {
int byteValue;
while ((byteValue = in.read()) != -1) {
processByte(byteValue);
}
}

Этот код функционально корректен, но крайне неэффективен: каждый вызов read() порождает системный вызов для чтения одного байта. Для файлов это означает обращение к диску, для сети — ожидание пакета.

Правильный подход — буферизованное чтение:
// Паттерн: буферизованное чтение с обработкой частичного заполнения
public void readBuffered(InputStream in) throws IOException {
byte[] buffer = new byte[8192]; // 8KB — типичный размер страницы ОС
int bytesRead;

while ((bytesRead = in.read(buffer)) != -1) {
processBuffer(buffer, bytesRead);
}
}

Здесь read(buffer) читает до 8192 байт за один системный вызов. Возвращаемое значение bytesRead обязательно проверяется: оно может быть меньше размера буфера, особенно при чтении из сети или при достижении конца файла. Признак конца потока -1 завершает цикл.

#Java #для_новичков #beginner #IO #NIO #InputStream #OutputStream
👍5
OutputStream: запись байтов

OutputStream — абстрактный класс, определяющий контракт для всех выходных байтовых потоков. Семантика записи также последовательная: байты отправляются в назначение в порядке вызова методов write.

void write(int b) — записывает один байт. Параметр типа int, но записываются младшие 8 бит. Старшие 24 бита игнорируются. Это согласовано с read(), возвращающим int.

void write(byte[] b) — записывает весь массив байт.

void write(byte[] b, int off, int len) — записывает len байт из массива b, начиная с позиции off.

void flush() — принудительно сбрасывает буферизованные данные в назначение. Многие реализации OutputStream используют внутреннюю буферизацию для повышения производительности: данные накапливаются в памяти и записываются пачками. flush() гарантирует, что все накопленные данные немедленно отправлены. Это критично для сценариев, где задержка недопустима: протоколы запрос-ответ, логирование в реальном времени, интерактивные сессии.

void close() — закрывает поток, освобождает ресурсы и неявно вызывает flush() для сброса оставшихся буферизованных данных. После закрытия потока любые последующие операции выбрасывают IOException.


Контракт flush(): гарантия доставки


Метод flush() не гарантирует физическую запись на диск или отправку по сети — он гарантирует только передачу данных из пользовательского буфера в операционную систему. Фактическая запись на носитель контролируется ОС и может быть отложена.

Для гарантии физической записи используется FileChannel.force(true) в NIO.
// Пример: flush перед ожиданием ответа
public void sendRequest(OutputStream out, byte[] request) throws IOException {
out.write(request);
out.flush(); // Гарантирует, что запрос отправлен до чтения ответа

// Теперь можно читать ответ, не рискуя deadlock из-за буферизации
}



Цепочка оберток: паттерн декоратора

Архитектура Java I/O построена на паттерне декоратора: базовые потоки (FileInputStream, SocketInputStream) предоставляют минимальную функциональность, а обертки (BufferedInputStream, DataInputStream, GZIPInputStream) добавляют возможности без изменения базового интерфейса.
// Цепочка оберток: буферизация + типизированное чтение + сжатие
try (InputStream fis = new FileInputStream("data.bin");
BufferedInputStream bis = new BufferedInputStream(fis, 8192);
DataInputStream dis = new DataInputStream(bis);
GZIPInputStream gzis = new GZIPInputStream(dis)) {

int magicNumber = dis.readInt(); // Чтение 4-байтового int
long timestamp = dis.readLong(); // Чтение 8-байтового long
double value = dis.readDouble(); // Чтение 8-байтового double
String label = dis.readUTF(); // Чтение строки в модифицированном UTF-8
}

Важное правило: закрывается только внешняя обертка. Вызов close() на GZIPInputStream проксируется через всю цепочку к FileInputStream, корректно освобождая все ресурсы. try-with-resources обрабатывает это автоматически.

Практический пример: копирование бинарного файла
public void copyBinaryFile(String sourcePath, String destPath) throws IOException {
// Буфер 8KB — оптимальный размер для большинства файловых систем
byte[] buffer = new byte[8192];

try (InputStream in = new FileInputStream(sourcePath);
OutputStream out = new FileOutputStream(destPath)) {

int bytesRead;
while ((bytesRead = in.read(buffer)) != -1) {
out.write(buffer, 0, bytesRead);
}

out.flush(); // Явный flush перед закрытием
}
}

Этот пример демонстрирует ключевые практики: буферизованное чтение для минимизации системных вызовов, проверку возвращаемого значения read для корректной обработки частичного чтения, запись ровно прочитанного количества байт, и явный flush перед закрытием. try-with-resources гарантирует закрытие обоих потоков даже при исключении.


#Java #для_новичков #beginner #IO #NIO #InputStream #OutputStream
👍5
Вакансия_Backend_Разработчик_2026_МИС3.pdf
95.2 KB
❗️❗️❗️ Ребят есть интересная вакансия 🧑‍💻

Требования:
- как я понял, от 1 года, но в резюме этого нет 🤫
- вилка 90-120к, не фонтан, но требования, возможно будут проще 🤷‍♀️
- гибрид или удаленка для ответственных 🙃
- наличие практического опыта работы с нейросетями/ИИ для ускорения разработки (не говорите, что у вас нет) 😄

Контакт:
https://t.me/OlesyaSbytova
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2🔥1🤯1