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
Что такое Random класс? 🤓

Ответ:

java.util.Random
— это класс для генерации псевдослучайных чисел с более гибкими возможностями, чем Math.random().

Позволяет создавать экземпляры с заданным seed'ом (при одинаковом seed последовательность будет одинаковой).

Основные методы: nextInt() (любое целое), nextInt(int bound) (от 0 до bound-1), nextLong(), nextDouble(), nextBoolean(), nextBytes().

Для многопоточных сценариев есть потокобезопасный ThreadLocalRandom.


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

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

Рольф Максимилиан Зиверт ( швед. [ˈrɔlf maksɪˈmǐːlɪan ˈsǐːvɛʈ] ; 6 мая 1896 — 3 октября 1966)шведский медицинский физик, основной вклад которого был в изучение биологических эффектов ионизирующего излучения. Зиверт (Zv), единица СИ, представляющая собой стохастический риск для здоровья, связанный с ионизирующим излучением, названа в его честь. Его называют «отцом радиационной защиты».

Андре Вейль ( / v eɪ / ;французский: [ɑ̃dʁe vɛj] ; 6 мая 1906 — 6 августа 1998)французский математик, известный своими основополагающими работами в области теории чисел и алгебраической геометрии. Он был одним из самых влиятельных математиков двадцатого века. Его влияние обусловлено как его оригинальным вкладом в удивительно широкий спектр математических теорий, так и следом, который он оставил в математической практике и стиле, как через некоторые из своих собственных работ, так и через группу Бурбаки, одним из главных основателей которой он был.


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

1949 – EDSAC, первый практический электронный цифровой компьютер с хранимой программой, совершает свою первую операцию.

1998 – Стив Джобс из Apple Inc. представляет первый iMac.

2002 – Основание SpaceX .


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

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

Почему System.out.println — антипаттерн для production-приложений


System.out.println — это комбинация трех элементов стандартной библиотеки Java: статического поля out класса java.lang.System, экземпляра java.io.PrintStream, и метода println этого экземпляра. Разберем каждый компонент.
Класс System содержит три статических поля для стандартных потоков ввода-вывода: in типа InputStream, out и err типа PrintStream. Поле out инициализируется JVM при старте виртуальной машины и представляет собой поток вывода, обычно связанный с консолью терминала или процесса-родителя. Поле err аналогично, но предназначено для вывода ошибок и обычно направлено в тот же физический поток, что и out, хотя может быть перенаправлено операционной системой отдельно.

PrintStream — это класс-обертка над байтовым потоком OutputStream, добавляющий удобные методы для вывода примитивных типов, строк и объектов. Ключевая особенность: PrintStream никогда не выбрасывает IOException. Вместо этого он устанавливает внутренний флаг ошибки trouble, который можно проверить методом checkError(). Это магическое подавление исключений делает System.out.println непригодным для сценариев, где критична надежность доставки сообщения — например, при записи в файл логов, где переполнение диска должно быть явно обнаружено и обработано.


Как работает под капотом

Инициализация потока

При старте JVM вызывается нативный метод initializeSystemClass(), который создает файловые дескрипторы для стандартных потоков через java.io.FileDescriptor. Для System.out создается FileOutputStream, обернутый в BufferedOutputStream, затем в PrintStream. Эта цепочка оберток обеспечивает буферизацию вывода и удобный API.
// Упрощенный псевдокод инициализации из OpenJDK
FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out);
BufferedOutputStream bufOut = new BufferedOutputStream(fdOut, 128);
System.out = new PrintStream(bufOut, true, charset); // autoFlush = true


Параметр autoFlush = true означает, что PrintStream будет принудительно сбрасывать буфер после каждого вызова println, printf или format, а также при записи массива байт. Это гарантирует немедленный вывод, но создает значительные накладные расходы на синхронизацию и системные вызовы.

Механика println

Метод println(String x) выполняет следующую последовательность:
Блокировка потока через synchronized(this) — PrintStream синхронизирован, что обеспечивает потокобезопасность, но создает contention при высокой конкуренции.
Вызов print(x), который преобразует строку в байты с использованием кодировки платформы по умолчанию (обычно UTF-8).
Запись байт в underlying BufferedOutputStream.
Вызов newLine() для записи разделителя строки, зависящего от платформы (\n для Unix, \r\n для Windows).
Если autoFlush включен, принудительный сброс буфера через flush().
Каждый вызов println порождает минимум один системный вызов write на уровне ОС после сброса буфера. При тысячах запросов в секунду это становится узким местом.


#Java #для_новичков #beginner #logging #System_out_println
👍2🔥2
Кодировка и платформенная зависимость

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