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
Кодировка и платформенная зависимость

PrintStream использует кодировку, определенную при создании. Для System.out JVM выбирает кодировку на основе системных свойств, переменных окружения или параметров запуска. Это создает платформенную зависимость: один и тот же символ может быть закодирован по-разному на Windows и Linux, что приводит к искажению логов при агрегации из разных источников. Профессиональные логгеры явно указывают UTF-8 и гарантируют консистентность кодировки независимо от платформы.


Проблема отсутствия уровней логирования

System.out.println выводит всё в одном потоке без разделения по важности. В production-системе разработчикам нужно различать рутинную информацию, детальную отладку, предупреждения и критические ошибки. Без уровней невозможно отфильтровать шум: при включении отладочного вывода консоль заполняется мегабайтами данных, среди которых теряются реальные проблемы.

Профессиональные фреймворки логирования предоставляют иерархию уровней — TRACE, DEBUG, INFO, WARN, ERROR — каждый из которых включает себя и все последующие. Это позволяет в development выводить DEBUG, в staging — INFO, а в production — только WARN и выше, без модификации кода. Конфигурация уровней выполняется внешним файлом, что позволяет оперативно изменять детализацию без перекомпиляции или перезапуска приложения.
С System.out.println единственный способ "отключить" отладку — удалить или закомментировать строки. Это нарушает принцип единственной ответственности: код смешивает бизнес-логику и управление выводом. При необходимости временно включить отладку для диагностики проблемы в production требуется redeploy, что недопустимо для высокодоступных систем.


Невозможность отключения вывода и накладные расходы

Каждый вызов System.out.println неизбежно выполняется. Даже если вывод перенаправлен в /dev/null, форматирование строки происходит в памяти JVM. Конкатенация строк через оператор + создает промежуточные объекты StringBuilder и String, нагружая garbage collector.
// Эта строка форматируется всегда, даже если вывод не нужен
System.out.println("User " + userId + " performed " + operation + " at " + Instant.now());


При отключенном логировании профессиональные фреймворки полностью исключают накладные расходы. SLF4J использует guard-метод logger.isDebugEnabled(), а параметризованные сообщения logger.debug("User {} not found", userId) выполняют подстановку только при активном уровне. Это критично для горячих путей выполнения, где лишние аллокации приводят к stop-the-world паузам сборщика мусора.


Отсутствие структурированного вывода

Вывод System.out.println — плоский текст без метаданных. Production-системы требуют временной метки с миллисекундной точностью, имени потока, имени класса и метода, номера строки, уровня серьезности. Ручное добавление этих полей к каждому вызову создает неподдерживаемый код, где бизнес-логика утопает в шаблонном форматировании.
// Антипаттерн: ручное форматирование метаданных
System.out.println("[" + Thread.currentThread().getName() + "] [" +
LocalDateTime.now() + "] [INFO] [" + getClass().getName() +
"] User " + userId + " not found");


Без структуры логи невозможно эффективно анализировать инструментами агрегации. ELK (Elasticsearch, Logstash, Kibana), Splunk, Grafana Loki ожидают машиночитаемый формат, обычно JSON, с предсказуемыми полями. Плоский текст требует сложного парсинга регулярными выражениями, что медленно, ненадежно и создает технический долг при изменении формата.


#Java #для_новичков #beginner #logging #System_out_println
👍3🔥1
Проблемы с производительностью

System.out направлен в PrintStream, который синхронизирован на уровне экземпляра. Каждый вызов println захватывает монитор объекта, блокируя конкурентные потоки. При высокой нагурке это создает серьезный contention: десятки потоков ожидают освобождения монитора для записи одного сообщения.

Профессиональные логгеры используют асинхронные appenders, которые декопируют поток бизнес-логики от потока записи на диск. Сообщение помещается в lock-free очередь (RingBuffer в Log4j2, LinkedBlockingQueue в Logback), и поток немедленно продолжает выполнение. Отдельный поток-потребитель асинхронно сбрасывает очередь на диск. Это устраняет блокировки и повышает пропускную способность на порядки.
Кроме того, PrintStream с autoFlush = true выполняет системный вызов write после каждого сообщения. Системные вызовы дороги: они требуют переключения контекста из userspace в kernelspace, инвалидации кэшей TLB и ожидания завершения I/O. Буферизованные appenders логгеров накапливают данные и сбрасывают их пачками, минимизируя количество системных вызовов.


Нет маршрутизации и политик хранения

System.out направлен единственным потоком. Невозможно разделить потоки: ошибки в один файл для оперативного мониторинга, бизнес-события в другой для аудита, отладка во временный буфер с ограниченным размером. Нет ротации файлов по размеру или времени — логи растут бесконечно, заполняя диск и приводя к отказу системы.

Профессиональные логгеры предоставляют RollingFileAppender с политиками TimeBasedRollingPolicy и SizeBasedTriggeringPolicy. Файлы автоматически архивируются, сжимаются и удаляются по достижении возраста или общего объема. Это критично для долгоживущих production-систем, где логи за год могут занимать терабайты.
Нет возможности динамической маршрутизации на основе содержимого сообщения. Нельзя направить логи аутентификации в security-мониторинг, а логи производительности в APM-систему. Маркеры (Markers) в SLF4J и фильтры в Logback/Log4j2 решают эту задачу декларативно.


Нет контекста и корреляции

В распределенных системах критична возможность отследить запрос через все компоненты — от API-шлюза до базы данных. Это требует привязки контекстной информации к каждому лог-сообщению: request ID, user ID, session ID, trace ID в распределенной трассировке.

System.out.println не предоставляет механизма для автоматической вставки контекста. Ручное добавление к каждому вызову невозможно в многопоточной среде, где контекст различается между потоками. MDC (Mapped Diagnostic Context) в SLF4J использует ThreadLocal для неявной привязки контекста к потоку выполнения, что позволяет декларативно включать поля контекста в каждое сообщение через шаблон конфигурации.


#Java #для_новичков #beginner #logging #System_out_println
👍6
Что выведет код?

public class Task060526 {
private static String getValue() {
try {
return "try";
} finally {
System.out.print("finally ");
}
}

public static void main(String[] args) {
System.out.print(getValue() + " ");
System.out.println("main");
}
}


#Tasks
👍2
👍2
Что такое BigDecimal? Когда его использовать? 🤓

Ответ:

BigDecimal
— класс для работы с десятичными числами с произвольной точностью.

Используется, когда критична точность вычислений (финансовые расчеты, налоги, валюты). float и double имеют проблемы с точным представлением дробей (например, 0.1 + 0.2).

BigDecimal позволяет задать масштаб (количество знаков после запятой) и режим округления. Операции создают новый объект (immutable).

Минус: медленнее примитивов. Создавать через строки: new BigDecimal("0.1"), а не new BigDecimal(0.1).


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

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

Па́вел Серге́евич Алекса́ндров (25 апреля [7 мая] 1896, Богородск — 16 ноября 1982, Москва) — советский математик, академик АН СССР (1953, член-корреспондент с 1929) и АПН РСФСР/СССР (1945). Профессор МГУ (1929). Основные труды по топологии, теории множеств, теории функций вещественного переменного, геометрии, вариационному исчислению, математической логике, основаниям математики.

Эдвин Герберт Лэнд (англ. Edwin Herbert Land; 7 мая 1909, Бриджпорт, штат Коннектикут — 1 марта 1991, Кембридж, штат Массачусетс) — американский учёный-оптик и изобретатель, основатель корпорации Polaroid. Он стал первым, кто использовал принципы поляризации во многих потребительских товарах и изобрёл одноступенный фотопроцесс. По количеству полученных патентов на изобретения — 535 — уступал только Томасу Эдисону.


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

1895 — в Петербурге русский физик и электротехник Александр Попов продемонстрировал свой «Прибор для обнаружения и регистрирования электрических колебаний».

1997 — компания Intel официально представила микропроцессор Pentium II.

2003 — первое в XXI веке для земного наблюдателя прохождение Меркурия по диску Солнца, доступное для наблюдателей большей части Африки и Евразии.


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

Тема: Ленивая инициализация синглтона через double-checked locking требует volatile.

Проблема: Паттерн double-checked locking (DCL) предназначен для ленивой инициализации синглтона с минимальной синхронизацией.

Классическая реализация без volatile содержит скрытую гонку данных из-за переупорядочивания инструкций (instruction reordering). Процесс создания объекта включает три этапа: выделение памяти, инициализация полей, присвоение ссылки переменной.

Компилятор и процессор могут переставить инициализацию и запись ссылки. В результате один поток может увидеть ненулевой, но еще не проинициализированный объект (partially constructed object), что приведет к непредсказуемому поведению, NullPointerException или чтению значений по умолчанию вместо заданных конструктором. Без volatile JVM не гарантирует happens-before связи между записью и последующим чтением.

Решение: Объявите поле синглтона как private static volatile. Модификатор volatile запрещает переупорядочивание операций с этим полем, обеспечивая, что запись ссылки произойдет только после полной инициализации объекта.

Начиная с Java 5 (и нового memory model), volatile обеспечивает правильный DCL.

Альтернативы: инициализация при загрузке класса (eager initialization) или использование enum-синглтона. Для современных проектов предпочтительнее подход с внутренним статическим классом (Initialization-on-demand holder idiom), который не требует ручной синхронизации.

public class Singleton {

//Антипаттерн: double-checked locking без volatile
private static Singleton instance; // отсутствует volatile!

public static Singleton getInstanceBad() {
if (instance == null) { // Первая проверка
synchronized (Singleton.class) {
if (instance == null) { // Вторая проверка
instance = new Singleton(); // Может быть переупорядочено!
}
}
}
return instance;
}

//Решение: volatile гарантирует корректность
private static volatile Singleton instance;

public static Singleton getInstanceGood() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton(); // Теперь безопасно
}
}
}
return instance;
}

//Лучшее решение без синхронизации: Initialization-on-demand holder
private static class Holder {
private static final Singleton INSTANCE = new Singleton();
}

public static Singleton getInstanceHolder() {
return Holder.INSTANCE; // Инициализация при первом обращении
}

//enum-синглтон (сериализация безопасна)
public enum EnumSingleton {
INSTANCE;
public void doSomething() { }
}

private Singleton() { }
}


Объяснение: Проблема DCL без volatile связана с тем, что запись ссылки instance = new Singleton() неатомарна.

Без volatile возможен следующий сценарий: поток A выполняет выделение памяти, записывает ссылку в instance, но инициализация конструктора еще не завершена. Поток B входит в метод, видит instance != null и возвращает недосозданный объект. volatile создает барьер памяти (memory barrier), который запрещает переупорядочивание и гарантирует, что все записи до момента присвоения будут видны всем потокам после.

В Java 5+ спецификация memory model была усилена, и DCL с volatile работает корректно. Однако идиома holder-класса предпочтительнее: она использует механизм потокобезопасной инициализации классов JVM, не требует явной синхронизации и короче.


#Java #советы
👍6
Немаленькое обновление devforge.ru

Что сделал:
- изменил визуал чата и профиля
- профиль можно редактировать и удалять, настраивать видимость полей для других пользователей
- можно поставить аватар
- чат подготовлен к следующей обнове где будут личные чаты
- в чате можно щелкнуть на юзера и посмотреть его профиль, подписаться на него (пока просто так)
- ну и еще всякой херни понаделал))))

Погнали тестить 💃
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4🔥1
Что выведет код?

public class Task070926 {
static int a = getB();
static int b = 5;
static int getB() { return b; }

public static void main(String[] args) {
System.out.println("a=" + a + ", b=" + b);
}
}


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

Ответ:

WeakHashMap
— это реализация Map, в которой ключи хранятся через слабые ссылки (WeakReference).

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

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


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

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

Кэйдзи Инафунэ (яп. 稲船 敬二 Инафунэ Кэйдзи, 8 мая 1965, Кисивада, Япония)японский игровой художник и продюсер компании Capcom, наиболее известный по созданию дизайна персонажей серии Mega Man, а также продюсированию игр Onimusha и Dead Rising.


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

1886 — Впервые производится Coca-cola — напиток, созданный доктором Джоном Пембертоном.


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

Глава 2. Логирование (Logging)

Архитектура логирования: фасад и реализация. SLF4J, Logback, Log4j2

До появления SLF4J Java-приложения напрямую зависели от конкретной библиотеки логирования — Log4j 1.x, java.util.logging (JUL), Jakarta Commons Logging.

Это создавало фундаментальную проблему: библиотека, использующая Log4j, несовместима с приложением, использующим JUL. При подключении сторонней библиотеки разработчик получал транзитивную зависимость от её логгера, что приводило к конфликтам classpath, дублированию конфигураций и невозможности централизованного управления.

Прямая зависимость от реализации нарушает принцип инверсии зависимостей из SOLID. Модуль высокого уровня (бизнес-логика) зависит от модуля низкого уровня (конкретный логгер). При смене реализации требуется модификация кода, а не только конфигурации.


Фасадный паттерн в логировании


Решением стало применение фасадного паттерна (Facade pattern) — создание абстрактного API, не зависящего от конкретной реализации. Фасад определяет контракт операций логирования: получение логгера, запись сообщений разных уровней, передача параметров, работа с маркерами и MDC. Реализация предоставляет конкретные механизмы: форматирование, запись в файл, ротацию, сетевую передачу.

Это разделение аналогично JDBC: приложение работает с интерфейсами Connection, Statement, ResultSet, не завися от конкретного драйвера базы данных. Смена базы данных требует только замены драйвера в classpath, без модификации кода.


SLF4J: Simple Logging Facade for Java

SLF4J, созданный Ceki Gülcü (также автор Log4j 1.x и Logback), стал де-факто стандартом фасада логирования в Java-экосистеме. Архитектура SLF4J состоит из трех компонентов:
- API (slf4j-api) — интерфейсы Logger, LoggerFactory, Marker, MDC. Это единственная зависимость, которую должна объявлять библиотека. API не содержит кода записи логов, только контракт.
- Binding (slf4j-logback, log4j-slf4j-impl) — адаптер, связывающий API с конкретной реализацией. Binding реализует интерфейс org.slf4j.spi.SLF4JServiceProvider и регистрирует фабрику логгеров для конкретной backend-системы.
- Bridge (jcl-over-slf4j, log4j-over-slf4j, jul-to-slf4j) — адаптеры для перенаправления вызовов из legacy-API в SLF4J. Это позволяет мигрировать постепенно: старый код, использующий Commons Logging, прозрачно направляется через SLF4J в актуальную реализацию.

Ключевое правило classpath: должен присутствовать ровно один binding. Наличие нескольких bindings приводит к предупреждению и непредсказуемому выбору реализации.


Получение логгера: LoggerFactory

Центральная точка входа в SLF4J — класс org.slf4j.LoggerFactory. Метод getLogger(Class<?>) возвращает именованный логгер, обычно с именем класса для точной идентификации источника сообщения.
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class OrderService {
// Конвенция: private static final, имя CLASS_NAME или просто logger
private static final Logger logger = LoggerFactory.getLogger(OrderService.class);

public void processOrder(String orderId) {
logger.info("Processing order: {}", orderId);
}
}


Имя логгера формирует иерархию, используемую для конфигурации уровней. Логгер com.example.service.OrderService наследует уровень от com.example.service, который наследует от com.example, и так до корневого логгера. Это позволяет управлять детализацией на уровне пакета или класса без перекомпиляции.


#Java #для_новичков #beginner #logging #Log4j2 #Logback #SLF4J
👍5
Logback: нативная реализация SLF4J

Logback, также созданный Ceki Gülcü, разработан как преемник Log4j 1.x и нативная реализация SLF4J.

Он состоит из трех модулей:
logback-core — базовые классы для appenders, layouts, фильтров. Независим от SLF4J, может использоваться для других целей.
logback-classic — реализация SLF4J API. Содержит LoggerContext — реестр логгеров, и систему конфигурации.
logback-access — специализированный модуль для логирования HTTP-запросов в сервлет-контейнерах.

Архитектура Logback построена на компонентах: Logger формирует событие LoggingEvent, которое передается через фильтры к Appender. Appender записывает событие через Layout в целевой ресурс — консоль, файл, сокет, базу данных. Appenders комбинируются: один логгер может иметь несколько appenders для дублирования вывода.
Конфигурация выполняется через XML (logback.xml, logback-test.xml), Groovy или программно. Logback поддерживает автоматическую перезагрузку конфигурации при изменении файла без перезапуска приложения.


Log4j2: следующее поколение

Apache Log4j2 — полная перепись Log4j 1.x, разработанная с учетом требований современных высоконагруженных систем.

Ключевые архитектурные отличия от Logback:
Асинхронные Loggers на базе LMAX Disruptor — lock-free RingBuffer, обеспечивающий пропускную способность в миллионы сообщений в секунду с минимальной латентностью. В Logback асинхронность реализована через AsyncAppender с LinkedBlockingQueue, что менее эффективно при экстремальных нагрузках.
Lazy initialization — Log4j2 не создает appenders до первого лог-сообщения, что ускоряет старт приложения. Logback инициализирует всю конфигурацию при загрузке.
Garbage-free logging — при определенных конфигурациях Log4j2 избегает аллокаций объектов при логировании, что критично для low-latency систем с чувствительным GC.
Plugin architecture — расширяемость через аннотации @Plugin, что упрощает создание кастомных appenders, layouts и фильтров.

Log4j2 может работать как самостоятельный фреймворк или через SLF4J API (log4j-slf4j-impl binding). Для приложений, уже использующих SLF4J, переход на Log4j2 требует только замены binding и конфигурации, без модификации кода.


Сравнение и выбор реализации

Выбор между Logback и Log4j2 зависит от требований проекта:
Logback предпочтителен для стандартных Spring Boot-приложений, где он является дефолтной реализацией. Конфигурация через logback-spring.xml интегрирована с профилями Spring. Logback проще в настройке, имеет меньше зависимостей, широко документирован.
Log4j2 выбирают для высоконагруженных систем, где критична пропускная способность логирования. Асинхронные логгеры на Disruptor обеспечивают порядок магнитуды лучшую производительность при пиковых нагрузках. Garbage-free режим важен для систем с жесткими требованиями к паузам GC.

Оба фреймворка поддерживают структурированное логирование в JSON, интеграцию с MDC, маркеры, фильтрацию и ротацию. Различия в производительности заметны только при экстремальных нагрузках — для большинства enterprise-приложений оба варианта адекватны.

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

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Task080526 {
public static void main(String[] args) {
Logger logger1 = LoggerFactory.getLogger(Task080526.class);
Logger logger2 = LoggerFactory.getLogger("test.logger");

System.out.println(logger1.getName());
System.out.println(logger2.getName());

Logger logger3 = LoggerFactory.getLogger(Task080526.class);
System.out.println(logger1 == logger3);
}
}


#Tasks
🗿3👍1
Что такое LinkedHashMap? Чем отличается от HashMap? 🤓

Ответ:

LinkedHashMap
— это наследник HashMap, который дополнительно поддерживает двусвязный список всех записей в порядке их добавления (insertion order) или порядке доступа (access order).

Благодаря этому итерация по LinkedHashMap происходит в предсказуемом порядке, в отличие от HashMap (порядок не гарантирован).

LinkedHashMap немного медленнее из-за поддержки списка. При использовании access order можно создать LRU-кэш (Least Recently Used), переопределив removeEldestEntry().


#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
Всем привет 😊

Сегодня не будет обучающих постов или постов с мемами.

В этот день мы, как и все адекватные жители планеты, чтим память миллионов человек отдавших свою жизнь в борьбе с фашистской Германией.

Чтим тех, кто сегодня как и тогда, воюет за свободу и независимость нашей Родины.

На фоне современной геополитической борьбы, попыток принизить и уничтожить память о героизме народов СССР, просто непозволительно игнорировать такой день.

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

С Днем Победы! ⭐️
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🔥3
История технологии сегодня — 09 мая

Россия,  Беларусь,  Молдова,  Армения,  Азербайджан,  Грузия,  Республика Абхазия,  Южная Осетия,  Казахстан,  Узбекистан (День памяти и почестей),  Туркменистан,  Кыргызстан,  Таджикистан,  Босния и Герцеговина ( Республика Сербская),  Северная Македония,  Сербия,  Черногория,  Израиль (с 2017 года) —День Побе́ды — праздник победы Красной армии и советского народа над нацистской Германией в Великой Отечественной войне 19411945 годов.

Установлен Указом 
Президиума Верховного Совета СССР от 8 мая 1945 года и ежегодно отмечается 9 мая

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

А́дам О́пель (нем. Adam Opel; 9 мая 1837, Рюссельсхайм — 8 сентября 1895, Рюссельсхайм) — основатель компании Adam Opel GmbH. Через 25 лет с момента основания Опель стал успешным международным изготовителем, экспортирующим швейные машины в Европу, США, Россию и Индию. В 1887 году Опель запустил в производство другую исключительно высоко оцененную машину — велосипед. За эти годы Опель стал самым большим в мире изготовителем велосипедов. В 1899 году Опель произвел первый автомобиль, потратив 37 лет на разработку и наработку производственного опыта. Хотя сам Адам Опель умер прежде, чем было начато автомобильное производство, семья Опель продолжила его видение, делая автомобиль доступным для как можно большего числа людей.

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

1996 — официальным талисманом Linux стал Tux.


#Biography #Birth_Date #Events #09мая
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3