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
С 30.05 по 12.06
Предыдущий пост(с 23.05 по 29.05)

Запись встреч/видео:
14. Transactional Outbox: как гарантировать публикацию события

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

Раздел 11. Работа с файлами, I/O и сетью (NIO.2)
Глава 1. Классический Java I/O (java.io (https://java.io/))

Байтовые потоки: абстрактные классы InputStream и OutputStream
FileInputStream – чтение байтов из файла. Путь данных в памяти JVM
FileOutputStream – запись байтов в файл. Путь данных от heap к диску
Проблема производительности побайтового ввода/вывода. Идея буфера
BufferedInputStream – буферизованное чтение. Путь данных через память JVM

[Совет по Java #045]
Тема: volatile не гарантирует атомарность.

[Совет по Java #046]
Тема: java.lang.Enum не может наследовать другой класс, потому что уже наследует Enum

[Совет по Java #047]
Тема: clone() — опасный метод с неясной семантикой.

[Совет по Java #048]
Тема: finalize() — устаревший и непредсказуемый.

[Совет по Java #049]
Тема: System.gc() не гарантирует запуск сборщика мусора.


Полезные статьи и видео:
Ты не хочешь стать программистом.

Как и всегда, задачи можно найти под тегом - #Tasks, вопросы с собеседований - #собеседование
👍2
Forwarded from ChatRoom (Java for Beginner) (Первожрец Java)
Я вот сижу продумываю систему оценки статей на deforge. Есть идеи? Как по вашему как это красиво реализовать? Чем хороши или плохи системы оценок и комментариев на Reddit StackOverflow или Хабр?
👍1
Как вам вариант? (сгенерировано)
🔥5
История технологии сегодня — 14 июня

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

Андре́й Андре́евич Ма́рков (2 (14) июня 1856, Рязань — 20 июля 1922, Петроград) — русский математик, академик, внёсший большой вклад в теорию вероятностейматематический анализ и теорию чисел. А. А. Марков является первооткрывателем обширного класса стохастических процессов с дискретной и непрерывной временно́й компонентой, названных его именем. Марковские процессы можно описать так: следующее состояние процесса зависит вероятностно только от текущего состояния. В то время, когда эта теория была построена, она считалась абстрактной, однако в настоящее время практические применения данной теории чрезвычайно многочисленны. Теория цепей Маркова выросла в огромную и весьма важную область научных исследований — теорию марковских случайных процессов, которая в свою очередь представляет основу общей теории стохастических процессов (см. также: Неравенство Маркова). А. А. Марков существенно продвинул классические исследования предшественников, касающиеся закона больших чисел и центральной предельной теоремы теории вероятностей, а также распространил их и на цепи Маркова.

Кири́лл Я́ковлевич Кондра́тьев (14 июня 1920, Рыбинск — 1 мая 2006, Санкт-Петербург)советский и российский геофизик. Основные труды относятся к исследованиям в области физики атмосферы, спутниковой метеорологии, атмосферной оптикеактинометрии, проблемам глобальной экологии и глобальным изменениям. Автор первой в мире монографии о спутниковой метеорологии (1963), серии монографий о дистанционном зондировании атмосферы и подстилающей поверхности, проблеме радиационного баланса Земли, фундаментальных основах природноресурсных космических исследований, сравнительном планетоведении. Впервые руководил экологическими исследованиями, проведёнными космонавтами из космоса. Соавтор научного открытия «Явление вертикально-лучевой структуры дневного излучения верхней атмосферы Земли».

Фёдор Васи́льевич То́карев (2 (14) июня 1871, станица МечётинскаяЧеркасский округОбласть Войска ДонскогоРоссийская империя — 7 июня 1968МоскваСССР) — русский и советский конструктор стрелкового оружия. Наиболее известные разработки: пистолет ТТ и винтовка СВТ-38/40.


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

1951 — в Вашингтоне поступил в продажу первый компьютер, созданный в США — UNIVAC I.


#Biography #Birth_Date #Events #14июня
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
История технологии сегодня — 15 июня

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

Евгений Викторович Колба́сьев (3 (15) июня 1862, Одесса, Российская империя — 20 ноября 1918, Инкерман, Крым) — русский изобретатель в области военно-морского дела, преподаватель Кронштадтской водолазной школы, капитан 1-го ранга. Автор оригинальной конструкции плавающей мины и нескольких проектов подводных лодок, в том числе диверсионной подводной лодки «Матрос Пётр Кошка», созданной в 1901 году. Колбасьев заметно опередил время, первыми создав секционный метод строительства подводных лодок. В разобранном виде подлодка помещалась в обычном железнодорожном вагоне, а процесс сборки занимал до 6 часов.

Поль Корню́ (фр. Paul Cornu; 15 июня 1881 года, Гло-ля-Феррьер — 6 июня 1944 года, Лизьё) — французский механик-изобретатель и авиатор; пионер вертолётостроения; первый в мире человек, поднявшийся в воздух на вертолёте (3 (13) ноября 1907).

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

1844 — Чарльз Гудьир запатентовал способ вулканизации резины.

1869 — Джон Хайат в Олбани (штат Нью-Йорк) запатентовал целлулоид.

2004 — Обнаружен первый сетевой вирус для мобильных телефонов — Cabir.


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

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

BufferedOutputStream – буферизованная запись. Путь данных от heap к диску

BufferedOutputStream — декоратор над OutputStream, добавляющий внутреннюю буферизацию к любому underlying потоку записи. Он решает зеркальную проблему по отношению к BufferedInputStream: накладные расходы системных вызовов при частых мелких операциях записи. Вместо немедленной отправки каждого байта в ОС, BufferedOutputStream накапливает данные в памяти и сбрасывает их пачками.

Ключевое отличие от чтения: запись буферизована по умолчанию, потому что ОС сама буферизует записи в page cache. Однако без BufferedOutputStream каждый вызов write(int) выполняет системный вызов, даже если данные попадают только в page cache. BufferedOutputStream устраняет эти избыточные вызовы.

Внутреннее устройство
// Упрощенная структура из OpenJDK
public class BufferedOutputStream extends FilterOutputStream {
// Внутренний буфер в heap JVM
protected byte[] buf;

// Количество байт, фактически записанных в буфер
protected int count;

// Конструкторы
public BufferedOutputStream(OutputStream out) {
this(out, 8192); // Размер по умолчанию
}

public BufferedOutputStream(OutputStream out, int size) {
super(out);
if (size <= 0) {
throw new IllegalArgumentException("Buffer size <= 0");
}
buf = new byte[size]; // Выделение в heap
}
}

Поля buf и count образуют линейный буфер накопления. При вызове write(int) байт помещается в buf[count++]. Когда count достигает buf.length, выполняется flushBuffer() — сброс накопленных данных в underlying поток.


Механика write() и путь данных

Посимвольная запись
public void write(int b) throws IOException {
if (count >= buf.length) {
flushBuffer(); // Буфер полон — сброс
}
buf[count++] = (byte) b; // Запись в heap, системный вызов отсутствует
}


Путь данных для write(int) при неполном буфере:
[Java: bos.write(65)]
-> [BufferedOutputStream: count < buf.length?]
-> [buf[count++] = 65] // Прямая запись в массив heap
-> [Возврат]

Никаких системных вызовов, никакого JNI. Байт записывается в массив в heap напрямую JVM-байткодом. Это на порядки быстрее, чем посимвольная запись через FileOutputStream.


Сброс буфера: flushBuffer()
private void flushBuffer() throws IOException {
if (count > 0) {
// Системный вызов: запись накопленных данных
out.write(buf, 0, count); // out — underlying FileOutputStream
count = 0; // Сброс счетчика
}
}


Путь данных для flushBuffer():
[Java: flushBuffer()]
-> [FileOutputStream.write(buf, 0, count)]
-> [JNI: нативный writeBytes]
-> [Ядро ОС: syscall write(fd, native_buf, count)]
-> [Page Cache: копирование в dirty pages]
-> [Пометка страниц как dirty]
-> [Возврат в userspace]
-> [Возврат в Java]
-> [count = 0]

Данные попадают в page cache ядра, но не немедленно на диск. Ядро асинхронно сбрасывает dirty pages фоновыми потоками.


Роль flush() и принудительный сброс

flush() в BufferedOutputStream выполняет два действия:
Сброс внутреннего буфера. flushBuffer() — запись накопленных данных в underlying поток.
Проксирование flush. out.flush() — сброс буферов underlying потока.
public void flush() throws IOException {
flushBuffer(); // Сброс buf в FileOutputStream
out.flush(); // Проксирование вниз по цепочке
}


Важное различие между flush() и физической записью на диск:
flush() гарантирует, что данные покинули JVM и попали в page cache ОС. Другие процессы могут читать эти данные.
flush() не гарантирует физическую запись на диск. При сбое питания данные в page cache теряются.
FileDescriptor.sync() или FileChannel.force(true) выполняют fsync(), который гарантирует физическую запись.
// Пример: гарантия доставки для критичных данных
try (BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream("critical.dat"))) {

bos.write(transactionData);
bos.flush(); // Сброс в page cache

// Для финансовых данных — fsync
bos.out.getFD().sync(); // Физическая запись на диск
}



Путь данных в памяти: детальный разбор

Сценарий: накопление данных в буфере
try (BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream("output.bin"), 8192)) {

for (int i = 0; i < 10000; i++) {
bos.write(i); // Накопление в buf, системные вызовы отсутствуют
}
// После цикла: count=10000, buf содержит данные в heap
}


Память в процессе:
buf[8192] — массив в heap, создан при конструировании
count — примитив в объекте BufferedOutputStream
Данные накапливаются в buf, GC не вовлечен в цикл

Когда count достигает 8192, следующий write() инициирует flushBuffer():
[Java: bos.write(byte_8192)]
-> [count >= 8192? да]
-> [flushBuffer()]
-> [FileOutputStream.write(buf, 0, 8192)]
-> [syscall write: 8192 байт в page cache]
-> [count = 0]
-> [buf[0] = byte_8192]
-> [count = 1]


Сценарий: закрытие потока
} // try-with-resources вызывает close()


close()
в BufferedOutputStream:
public void close() throws IOException {
try (OutputStream os = out) {
flush(); // Неявный flush перед закрытием
} // out.close() вызывается автоматически
}


Путь данных при закрытии:
flush() — сброс остатка буфера в underlying поток
out.flush() — сброс в page cache ОС
out.close() — закрытие файлового дескриптора
Объекты bos, buf, out становятся недостижимыми
GC собирает их при следующей сборке


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

Жизненный цикл буфера при записи
public void writeRecords(String path, List<Record> records) throws IOException {
// buf создается в Eden space
try (BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream(path))) {

for (Record record : records) {
byte[] data = record.toBytes(); // Новый массив при каждой итерации!
bos.write(data); // Копирование в buf или flushBuffer()
// data становится мусором
}

bos.flush(); // Явный сброс остатка

} // close() с неявным flush()

// buf и все data[] собираются GC
}

В этом примере каждая итерация создает массив data. Эти массивы короткоживущие и нагружают GC. Оптимизация — переиспользование или прямая запись в BufferedOutputStream без промежуточных массивов.

Оптимизация: прямая запись без промежуточных массивов
public void writeRecordsOptimized(String path, List<Record> records) throws IOException {
// Переиспользуемый буфер для сериализации
ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);

try (BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream(path))) {

for (Record record : records) {
baos.reset(); // Сброс без создания нового объекта

record.serialize(baos); // Запись в переиспользуемый baos

byte[] data = baos.toByteArray(); // Все еще создается массив
// Лучше: запись напрямую в bos, минуя baos
}
}
}



Идеальное решение — сериализация напрямую в BufferedOutputStream, без промежуточных массивов:
public void writeRecordsDirect(String path, List<Record> records) throws IOException {
try (DataOutputStream dos = new DataOutputStream(
new BufferedOutputStream(new FileOutputStream(path)))) {

for (Record record : records) {
dos.writeUTF(record.getId()); // Прямая запись в buf
dos.writeLong(record.getTimestamp()); // Без промежуточных массивов
dos.writeInt(record.getValue());
// Данные накапливаются в buf BufferedOutputStream
}

} // Автоматический flush() и close()
}

DataOutputStream пишет примитивы напрямую в underlying поток, который буферизован. Никаких временных массивов, минимальная нагрузка на GC.
Проблема: забытый flush() и потеря данных
java
// Антипаттерн: данные могут не попасть в файл
public void dangerousWrite(String path, String data) throws IOException {
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream(path));
bos.write(data.getBytes());
// flush() не вызван!
// close() не вызван!
// При выходе из метода: buf содержит данные, но не сброшен
// GC финализирует объект, close() вызовется через Cleaner, но с задержкой
}


В этом коде:
Данные остаются в buf в heap
Файловый дескриптор открыт, данные не записаны в ОС
Если приложение завершится до финализации — данные потеряны
Даже при финализации задержка непредсказуема

Правильный подход — try-with-resources, который гарантирует close() с неявным flush():
// Правильно: гарантированный flush и close
public void safeWrite(String path, String data) throws IOException {
try (BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream(path))) {
bos.write(data.getBytes());
// flush() вызовется неявно в close()
}
}


Практический пример: буферизованное копирование файла
public class BufferedFileCopy {

private static final int BUFFER_SIZE = 8192;

public static void copy(String sourcePath, String destPath) throws IOException {
// Буфер для чтения — внешний, создается в heap
byte[] buffer = new byte[BUFFER_SIZE];

// BufferedInputStream: buf[8192] в heap для накопления чтения
// BufferedOutputStream: buf[8192] в heap для накопления записи
// Итого: ~16KB в heap на время копирования

try (BufferedInputStream bis = new BufferedInputStream(
new FileInputStream(sourcePath), BUFFER_SIZE);
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream(destPath), BUFFER_SIZE)) {

int bytesRead;
// Цикл без аллокаций в heap — GC не вовлечен
while ((bytesRead = bis.read(buffer)) != -1) {
bos.write(buffer, 0, bytesRead);
}

// Явный flush для гарантии сброса остатка
bos.flush();

} // Автоматический close() для обоих потоков

// buffer, bis.buf, bos.buf — все становятся недостижимым
// GC собирает при следующей minor collection
}

// Альтернатива: без внешнего буфера, используя внутренние буферы оберток
public static void copyOptimized(String sourcePath, String destPath) throws IOException {
try (BufferedInputStream bis = new BufferedInputStream(
new FileInputStream(sourcePath));
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream(destPath))) {

int byteValue;
// Побайтово, но фактически буферизовано
// Внешний буфер не нужен — экономия 8KB в heap
while ((byteValue = bis.read()) != -1) {
bos.write(byteValue);
}
}
}
}


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

import java.io.*;

public class Task150626 {
public static void main(String[] args) throws IOException {

File f = new File("data.txt");

FileOutputStream fos = new FileOutputStream(f);

BufferedOutputStream bos = new BufferedOutputStream(fos, 1024);

bos.write("Java".getBytes());
System.out.println(f.length());
bos.close();
System.out.println(f.length());
}
}


#Tasks
👍4
Варианты ответа:
Anonymous Quiz
17%
0 0
17%
4 4
50%
0 4
17%
4 0
👍2
Что такое StackOverflowError и как его диагностировать? 🤓

Ответ:

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

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

Диагностировать можно:
1) посмотреть stack trace — последние вызовы повторяются.
2) увеличить размер стека (флаг -Xss).
3) переписать рекурсию на итерацию или хвостовую рекурсию (Java не оптимизирует её сама).

Также может возникать при большом количестве вложенных вызовов (например, парсинг глубокого JSON).



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

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

Алекса́ндр Алекса́ндрович Фри́дман (4 (16) июня 1888[3], Санкт-Петербург — 16 сентября 1925, Ленинград) — русский и советский математикгидромеханикфизик-теоретик и геофизик. Основоположник современной физической космологии, автор исторически первой нестационарной модели Вселенной (Вселенная Фридмана), один из создателей современной динамической метеорологии. Основные работы посвящены проблемам динамической метеорологии (теории атмосферных вихрей и порывистости ветра, теории разрывов непрерывности в атмосфере, атмосферной турбулентности), гидродинамике сжимаемой жидкости, физике атмосферы и релятивистской космологии. В июле 1925 года с научными целями совершил полёт на аэростате вместе с пилотом Павлом Федосеенко, достигнув рекордной по тому времени для СССР высоты 7400 м. Фридман одним из первых освоил математический аппарат теории гравитации Эйнштейна и начал читать в университете курс тензорного исчисления как вводную часть к курсу общей теории относительности. В 1923 году вышла в свет его книга «Мир как пространство и время» (переиздана в 1965 году), познакомившая широкую публику с новой физикой.

Юлиус Плю́ккер (нем. Julius Plücker; 16 июня или 16 июля 1801 года, Эльберфельд — 22 мая 1868 года, Бонн) — немецкий математик и физик, работавший в области аналитической геометрии, был пионером в области исследования катодных лучей, что впоследствии привело к открытию электрона. Также занимался исследованиями кривых Ламе.


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

1911 — основана корпорация IBM.

1963 — стартовал космический корабль «Восток-6» с Валентиной Терешковой, первой в мире женщиной-космонавтом.


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

Тема: Optional не предназначен для полей класса и для параметров методов.

Проблема: Optional был создан как ограниченный механизм для возвращаемых значений методов, чтобы явно указать возможность отсутствия результата.

Использование Optional в полях класса нарушает сериализацию: Optional не реализует Serializable, и многие фреймворки (Hibernate, Jackson, сериализация Java) работают с ним некорректно или требуют дополнительной настройки. Кроме того, поле-Optional создает избыточность — само поле уже может быть null, а его обертка добавляет еще один уровень. Использование Optional в параметрах методов делает API громоздким: вызывающий код вынужден создавать Optional.of() или Optional.empty(), что усложняет чтение и не дает реальных преимуществ.

Решение: Используйте Optional только для возвращаемых типов методов, которые могут не возвращать значение. Для полей класса используйте null-допустимые типы с аннотациями (@Nullable@NotNull) или библиотеки вроде Lombok. Для параметров методов используйте перегрузки методов или явную проверку на null. Если параметр может быть опциональным, лучше применить паттерн Builder или передавать отдельный флаг.
import java.util.Optional;
import java.io.Serializable;

public class OptionalUsage {

//Антипаттерн: Optional как поле класса
static class BadEntity implements Serializable {
private Optional<String> name = Optional.empty(); // Не сериализуется!
private Optional<Integer> age; // Hibernate не поймет
// getter/setter
}

//Правильно: просто nullable поле
static class GoodEntity implements Serializable {
private String name; // null = отсутствует
private Integer age; // null = отсутствует
}

//Антипаттерн: Optional в параметре метода
public static void badMethod(Optional<String> param) {
// Вызывающему нужно писать badMethod(Optional.of("text"))
if (param.isPresent()) { /* ... */ }
}

//Решение 1: перегрузка метода
public static void goodMethod() {
// без параметра
}

public static void goodMethod(String param) {
// с параметром (может быть null)
}

//Решение 2: проверка на null
public static void betterMethod(String param) {
if (param != null) { /* ... */ }
}

//Единственное правильное место: возвращаемое значение
public static Optional<String> findUserById(long id) {
// поиск в БД
return id > 0 ? Optional.of("User") : Optional.empty();
}

public static void main(String[] args) {
// Использование Optional из возврата
findUserById(10).ifPresent(System.out::println);

// Перегрузка вместо Optional параметра
goodMethod(); // без параметра
goodMethod("text"); // с параметром
}
}


Объяснение:
 Создатели Java (в частности, Брайан Гетц) неоднократно подчеркивали, что Optional предназначен исключительно для возвращаемых значений. Он не должен использоваться в полях, параметрах методов, коллекциях и как ключ в Map. Причина: Optional не сериализуем (есть обходные пути, но они хрупкие), и его использование в полях вводит в заблуждение — поле уже может быть null, а обертка не добавляет безопасности. Для параметров методов Optional создает лишний объект и не улучшает читаемость. Вместо этого используйте явную проверку на null, аннотации @Nullable или @NotNull, а для возврата — Optional.

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

import java.io.*;
import java.util.Optional;

class Data160626 implements Serializable {
Optional<String> value = Optional.of("secret");
}

public class Task160626 {
public static void main(String[] args) throws Exception {
Data160626 d = new Data160626();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(d);
oos.close();

ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()));
Data160626 d2 = (Data160626) ois.readObject();
System.out.println(d2.value.get());
}
}


#Tasks
👍3
👍3
Вот это и случилось))) Ютуб канал перегнал по популярности телеграмм-канал.

Что думаете? Помоему закономерно, хотя труда вложенного в телеге гораздо больше....

Хотя если оглянуться то и 70 видео сами себя не записали...

😎
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥11🍾2
Что такое OutOfMemoryError? Какие бывают виды? 🤓

Ответ:

OutOfMemoryError выбрасывается, когда JVM не может выделить память для нового объекта.

Виды:
1) Java heap space — кончилась память в куче (heap).
2) Metaspace / PermGen — кончилась память для метаданных классов.
3) GC overhead limit exceeded — GC слишком много работает (более 98% времени) и освобождает мало.
4) Unable to create new native thread — невозможно создать новый поток (мало памяти ОС).
5) Requested array size exceeds VM limit — массив больше допустимого.

Причины и решения разные: увеличение heap, утечки памяти, настройка GC.



#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5