Java for Beginner
870 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
Что такое Stack и Queue в Java? Какие реализации есть? 🤓

Ответ:

Stack
 — класс (устаревший, наследует Vector).

Рекомендуется использовать Deque как стек: Deque<E> stack = new ArrayDeque<>(); с методами push(), pop(), peek(). 

Queue — интерфейс. Основные методы: add()/offer() (добавить), remove()/poll() (удалить и вернуть), element()/peek() (посмотреть без удаления). 

Queue может быть FIFO (обычная очередь) или LIFO (стек). Реализации: ArrayDeque (циклический массив), LinkedList (связный список), PriorityQueue (приоритетная очередь на куче).


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

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

Ари Абрамович Штернфельд (14 мая 1905, Серадз, Калишская губерния, Российская империя — 5 июля 1980, Москва, СССР) — учёный, один из пионеров современной космонавтики.
Рассчитал и теоретически исследовал множество траекторий 
космических полётов, определив энергетически оптимальные. Эти траектории, с предварительным удалением от цели, позволяющие значительно экономить топливо, называют «штернфельдовскими». Он ввёл понятие космических скоростей и рассчитал их стартовые значения. Сформулировал проблему существования «сезонов космической навигации». Термины «космонавтика», «первая космическая скорость», «космодром» введены им впервые в его книге «Введение в космонавтику» (1934; на русском языке — Москва, 1937). Впервые он применил теорию относительности для анализа межзвёздных полётов, для повышения точности траекторных расчётов и доказал, что достижение звезд, в принципе, возможно в течение человеческой жизни.

Михаи́л Дми́триевич Аге́ев (14 мая 1931, Черемхово, Иркутская область — 19 ноября 2005, Владивосток) — советский и российский учёный, специалист в области систем навигации и управления движущимися объектами, академик РАН (1992). За глубокие исследования в области морских технологий, создание и применение глубоководных автономных необитаемых подводных аппаратов при решении ряда уникальных и важных, государственных задач в океане на больших глубинах Михаил Дмитриевич Агеев был награждён орденом Трудового Красного Знамени, орденом Почёта (1996) и медалью «300 лет Российского флота». В 1990 году ему был присуждён международный диплом «INTERVETION / ROV’90» первой степени за лучшую работу года и вклад в прогресс мировой подводной робототехники.
Автор многочисленных научных трудов и изобретений. Состоял членом многих специализированных советов по защите докторских и кандидатских диссертаций, председателем Объединённого учёного совета по физико-математическим и техническим наукам, под его редакцией вышли в свет многие научные труды и издания. Член американского научного Общества морских технологий, член ряда оргкомитетов международных форумов.


Марк Э́ллиот Цу́керберг (англ. Mark Elliot Zuckerberg, [ˈzʌkərbɜːrɡ]; род. 14 мая 1984, Уайт-Плейнс, Нью-Йорк, США) — американский медиамагнат, интернет-предприниматель и филантроп. Известен как соучредитель компании Meta (ранее — Facebook, Inc.) и является её председателем, главным исполнительным директором и контролирующим акционером.


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

2009 — запущен на орбиту телескоп «Гершель», названный в честь британского астронома Уильяма Гершеля.


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

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

Уровни логирования: TRACE, DEBUG, INFO, WARN, ERROR. Когда что использовать. Иерархия и фильтрация

Логирование без уровней — это поток неразличимых сообщений, где критическая ошибка теряется среди рутинных уведомлений о старте компонента. Уровни логирования — это система классификации сообщений по степени серьезности и детализации, которая позволяет разделить диагностический вывод на категории и фильтровать их в зависимости от окружения и задачи.

SLF4J определяет пять стандартных уровней, упорядоченных по возрастанию серьезности: TRACE, DEBUG, INFO, WARN, ERROR. Каждый уровень включает в себя и все последующие. Если логгер настроен на уровень INFO, он пропускает сообщения INFO, WARN и ERROR, но подавляет TRACE и DEBUG. Это свойство называется иерархией уровней и является фундаментальным механизмом управления объемом логов.


Иерархия уровней SLF4J

Иерархия строится от наименее серьезного к наиболее серьезному. TRACE находится на дне пирамиды — это максимальная детализация, используемая исключительно для отладки сложных алгоритмов. DEBUG следует выше — диагностическая информация, полезная при разработке и расследовании проблем. INFO — стандартный уровень для рутинных событий приложения. WARN — сигнал о нештатной, но не критичной ситуации. ERROR — фиксация сбоев, нарушающих функциональность.

Logback расширяет эту шкалу двумя техническими уровнями: ALL и OFF. ALL пропускает все сообщения независимо от уровня, OFF подавляет все сообщения полностью. Эти уровни не используются в коде приложения, а применяются в конфигурации для полного включения или отключения логирования отдельных компонентов.


TRACE — трассировка выполнения

TRACE — самый низкий и самый детальный уровень. Он предназначен для трассировки потока выполнения на уровне отдельных шагов алгоритма, входа и выхода из методов, итераций циклов и ветвлений условий. SLF4J исторически не рекомендовал использование TRACE, добавив его только под давлением сообщества, поскольку существуют альтернативы или потому что сообщения TRACE часто избыточны. Тем не менее, уровень остается полезным для локальной отладки сложных рекурсивных или конечно-автоматных алгоритмов.

TRACE никогда не включается в production. Объем данных, генерируемый на этом уровне, на порядки превышает возможности дисковой подсистемы и систем агрегации. Включение TRACE в высоконагруженном сервисе приводит к деградации производительности из-за частых системных вызовов записи и переполнению буферов асинхронных appenders.
public void quickSort(int[] array, int left, int right) {
logger.trace("Entering quickSort(left={}, right={})", left, right);

if (left < right) {
int pivot = partition(array, left, right);
logger.trace("Pivot index={}, array state={}", pivot, Arrays.toString(array));

quickSort(array, left, pivot - 1);
quickSort(array, pivot + 1, right);
}

logger.trace("Exiting quickSort(left={}, right={})", left, right);
}

В этом примере TRACE фиксирует каждый рекурсивный вызов и состояние массива. При отладке алгоритма сортировки это позволяет восстановить полную историю преобразований. В production эти строки бесполезны и подавляются конфигурацией.


#Java #для_новичков #beginner #logging #Log4j2 #Logback #SLF4J #INFO #DEBUG #WARN #ERROR #TRACE
👍5
DEBUG — диагностика

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

Ключевое различие между TRACE и DEBUG: DEBUG-логирование должно быть пригодным для включения в production на ограниченное время при расследовании инцидента. TRACE-логирование настолько детально, что его включение в production технически невозможно без деградации системы. DEBUG — это баланс между информативностью и производительностью.
public User authenticate(String username, String passwordHash) {
logger.debug("Authentication attempt for user={}", username);

User user = userRepository.findByUsername(username);
logger.debug("User lookup result: found={}, status={}",
user != null, user != null ? user.getStatus() : "N/A");

if (user == null || !user.getPasswordHash().equals(passwordHash)) {
logger.debug("Authentication failed for user={}: invalid credentials", username);
return null;
}

if (user.getStatus() == UserStatus.LOCKED) {
logger.debug("Authentication failed for user={}: account locked", username);
return null;
}

logger.debug("Authentication successful for user={}, roles={}",
username, user.getRoles());
return user;
}

Этот метод логирует ключевые точки принятия решений без избыточной детализации. При расследовании проблемы аутентификации разработчик видит, на каком этапе произошел отказ: пользователь не найден, неверный пароль или заблокированный аккаунт.


INFO — рутинные события

INFO — стандартный уровень для production. Он фиксирует значимые события жизненного цикла приложения: запуск и остановка сервиса, успешное завершение пакетной операции, вход и выход пользователя, изменение состояния сущности. INFO-сообщения формируют операционную хронологию системы — просмотр логов уровня INFO и выше дает обзор основных событий без погружения в детали.

INFO не предназначен для ежесекундных событий. Если метод вызывается тысячи раз в минуту, его логирование на уровне INFO создаст неуправляемый поток данных. INFO должен использоваться для событий, которые происходят относительно редко и представляют интерес для операционной команды.
@Service
public class OrderProcessingService {

@EventListener
public void onApplicationReady(ApplicationReadyEvent event) {
logger.info("Order processing service started, version={}, profile={}",
buildProperties.getVersion(),
Arrays.toString(environment.getActiveProfiles()));
}

public Order processOrder(OrderRequest request) {
logger.info("Processing orderId={}, customerId={}, amount={}",
request.getOrderId(), request.getCustomerId(), request.getAmount());

Order order = executeBusinessLogic(request);

logger.info("Order {} processed successfully, status={}, durationMs={}",
order.getId(), order.getStatus(), order.getProcessingDuration());
return order;
}
}

В этом примере INFO фиксирует старт сервиса и успешное завершение бизнес-операции. Оператор, просматривая логи, видит, что заказ обработан, но не видит деталей валидации каждого поля — это остается на уровне DEBUG.

#Java #для_новичков #beginner #logging #Log4j2 #Logback #SLF4J #INFO #DEBUG #WARN #ERROR #TRACE
👍4
WARN — предупреждения

WARN сигнализирует о нештатной ситуации, которая не нарушает основную функциональность, но требует внимания. Это неожиданное поведение, отклонение от нормы, ситуация, которая может указывать на надвигающуюся проблему. WARN не означает ошибку — приложение продолжает работу, но что-то пошло не так.

Классические сценарии для WARN: использование устаревшего API, получение неожиданного формата данных от внешней системы, превышение порога времени выполнения операции, отказ вторичного сервиса при наличии fallback, повторная попытка операции после временного сбоя.

public void sendNotification(User user, Notification notification) {
try {
notificationGateway.send(user.getEmail(), notification);
logger.info("Notification sent to user={}", user.getId());
} catch (GatewayTimeoutException e) {
logger.warn("Notification gateway timeout for user={}, will retry asynchronously",
user.getId());
enqueueForRetry(user, notification);
}
}

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


ERROR — ошибки

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

Важное правило: не каждое исключение должно логироваться на уровне ERROR. Если метод обрабатывает исключение и предпринимает корректирующие действия (retry, fallback, пропуск элемента), уровень должен быть WARN. ERROR используется, когда операция завершилась неудачно и нет механизма восстановления, или когда исключение пробрасывается на верхний уровень для аварийной обработки.
public void chargePayment(Payment payment) {
try {
paymentGateway.charge(payment);
logger.info("Payment {} charged successfully", payment.getId());
} catch (PaymentGatewayException e) {
if (e.isRetryable()) {
logger.warn("Payment {} failed with retryable error, scheduling retry",
payment.getId());
scheduleRetry(payment);
} else {
logger.error("Payment {} failed with non-retryable error: {}",
payment.getId(), e.getMessage(), e);
markAsFailed(payment);
}
}
}

В этом примере retryable-ошибка логируется как WARN, потому что система восстанавливается автоматически. Non-retryable ошибка — ERROR, потому что платеж окончательно не выполнен и требует ручного разбора.


#Java #для_новичков #beginner #logging #Log4j2 #Logback #SLF4J #INFO #DEBUG #WARN #ERROR #TRACE
👍5
Фильтрация и наследование уровней

Логгеры в SLF4J и Logback организованы в иерархическую структуру на основе их имен. Логгер com.example.service.OrderService наследует уровень от com.example.service, который наследует от com.example, и так до корневого логгера. Это свойство называется наследованием уровней.
Когда логгер не имеет явно назначенного уровня, он наследует уровень ближайшего предка, у которого уровень определен. Корневой логгер всегда имеет уровень и служит последней инстанцией. Это позволяет управлять детализацией на уровне пакета или класса без перекомпиляции.
// Псевдокод конфигурации Logback
Logger root = LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
root.setLevel(Level.INFO);

Logger servicePackage = LoggerFactory.getLogger("com.example.service");
servicePackage.setLevel(Level.DEBUG);

Logger orderService = LoggerFactory.getLogger("com.example.service.OrderService");
// orderService не имеет явного уровня, наследует DEBUG от com.example.service

Свойство additivity определяет, будет ли сообщение, обработанное логгером, передаваться родительским логгерам. По умолчанию additivity равно true, что означает, что сообщение проходит через всю цепочку appenders от конкретного логгера до корневого.

Если additivity установлено в false, сообщение обрабатывается только appenders данного логгера и не поднимается выше.
<!-- Logback: отключение additivity для изоляции вывода -->
<logger name="com.example.audit" level="INFO" additivity="false">
<appender-ref ref="AUDIT_FILE"/>
</logger>


В этом примере логгер com.example.audit направляет сообщения только в файл аудита, не дублируя их в корневой appender. Это критично для разделения потоков: бизнес-аудит не должен попадать в общий лог ошибок.
Практические рекомендации по выбору уровня

Выбор уровня — это не субъективное предпочтение, а архитектурное решение, влияющее на наблюдаемость системы.

Несколько правил, выработанных практикой:
Правило единственного уровня для исключения. Одно и то же событие не должно логироваться на разных уровнях в разных местах. Если метод перехватил исключение и залогировал его как ERROR, вызывающий код не должен логировать его повторно. Дублирование создает шум и затрудняет анализ.
Правило восстановимости. Если операция может быть восстановлена автоматически — WARN. Если восстановление невозможно — ERROR. Если это ожидаемое поведение — INFO или ниже.
Правило частоты. События, происходящие чаще нескольких раз в минуту на экземпляр, не должны логироваться на INFO. Используйте DEBUG или агрегируйте метриками.
Правило контекста. Сообщение должно содержать достаточно контекста для понимания проблемы без чтения кода. Вместо logger.error("Failed") используйте logger.error("Payment processing failed for orderId={}, gateway={}", orderId, gatewayId).
Правило guard-методов. Для дорогостоящих DEBUG и TRACE сообщений используйте logger.isDebugEnabled() или параметризованные сообщения SLF4J для исключения накладных расходов при отключенном уровне.
// Правильно: ленивое вычисление через параметризацию
logger.debug("Processing batch of {} items, estimated memory={}MB",
batchSize, estimatedMemory);

// Избыточно: guard-метод не нужен для простых параметров
if (logger.isDebugEnabled()) {
logger.debug("Simple message");
}

// Оправдано: guard для дорогостоящих операций
if (logger.isDebugEnabled()) {
logger.debug("Complex state: {}", serializeFullObjectGraph(state));
}



Согласованность уровней в распределенных системах

В микросервисной архитектуре согласованность уровней между сервисами критична для корреляции событий. Если один сервис логирует отказ внешнего вызова как ERROR, а вызываемый сервис фиксирует тот же отказ как WARN, оператор теряет единую картину. Рекомендуется выработать командный стандарт: ERROR — это сбой, который требует немедленного вмешательства и не может быть восстановлен автоматически в рамках текущего запроса. WARN — сбой с автоматическим восстановлением или деградация без потери функциональности.


#Java #для_новичков #beginner #logging #Log4j2 #Logback #SLF4J #INFO #DEBUG #WARN #ERROR #TRACE
👍5
Что выведет код?

import java.util.*;

public class Task140526 {
public static void main(String[] args) {
List<Integer> list = List.of(1, 2, 3, 4, 5);
Collections.shuffle(list);
System.out.println(list);
}
}



#Tasks
👍2
👍4
Что такое Collections класс? Какие полезные методы там есть? 🤓

Ответ:

java.util.Collections
 — это утилитный класс с статическими методами для работы с коллекциями.

Основные методы: 
сортировка — sort(), binarySearch(); 
перемешивание — shuffle(); 
переворот — reverse(); 
поиск мин/макс — min(), max(); 
замена — replaceAll(), fill(), swap(); 
создание неизменяемых оболочек — unmodifiableList(), unmodifiableSet(), unmodifiableMap(); 
синхронизированные обертки — synchronizedList(), synchronizedMap() (для потокобезопасности).

Также содержит пустые коллекции: emptyList(), emptySet(), emptyMap().


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

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

Влади́мир Григо́рьевич Фёдоров (3 (15) мая 1874, Санкт-Петербург — 19 сентября 1966, Москва) — русский и советский конструктор стрелкового оружия, генерал-лейтенант инженерно-технической службы (1943), академик Академии артиллерийских наук (1946), профессор (1941), доктор технических наук (1940), Герой Труда (1928). Изобрел первое в мире ружьё-пулемёт, которое впервые в истории получило название автомат[6]. Кроме того уже в советские годы под руководством Фёдорова впервые в мире были созданы унифицированные образцы оружия. Да и сама идея унификации огнестрельного оружия получила признание впервые в мире и впервые в истории. Работа над унификацией стрелкового оружия на базе автомата Фёдорова сыграла важную роль для дальнейшего развития автоматического оружия в СССР и в мире.

Пьер Кюри́ (фр. Pierre Curie; 15 мая 1859 года, Париж, Французская империя — 19 апреля 1906 года, там же, Третья Республика) — французский учёный-физик, один из первых исследователей радиоактивности, член Французской академии наук, лауреат Нобелевской премии по физике за 1903 год.


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

1718 — английский юрист Джеймс Пакл запатентовал один из первых пулемётов — ружьё Пакла.


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

Тема: SimpleDateFormat не потокобезопасен.

Проблема: SimpleDateFormat хранит изменяемое внутреннее состояние (объект Calendar, позиции парсинга и буферы форматирования).

Методы format() и parse() модифицируют это состояние. При конкурентном вызове одного экземпляра из разных потоков возникает состояние гонки: один поток может изменить календарь, пока другой читает его. Это проявляется в виде NumberFormatExceptionParseException, неверных дат или даже бесконечных циклов.

Ошибка коварна — в однопоточном коде всё работает идеально, проблемы возникают только под нагрузкой, что затрудняет отладку.

Решение: Для Java 8+ используйте неизменяемый (immutable) и потокобезопасный DateTimeFormatter.

В Java 7 и ниже применяйте ThreadLocal для хранения отдельного экземпляра SimpleDateFormat на поток, либо синхронизируйте доступ, либо создавайте новый объект при каждом вызове. DateTimeFormatter – предпочтительный вариант: он не содержит состояния, поддерживает новые Date/Time API и работает быстрее.
public class DateFormatSafety {

//Антипаттерн: общий SimpleDateFormat
private static final SimpleDateFormat BAD_FORMAT =
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

public static String badFormat(Date date) {
return BAD_FORMAT.format(date); // Гонка! Сломанные данные
}

//Решение 1: DateTimeFormatter (Java 8+)
private static final DateTimeFormatter FORMATTER =
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

public static String goodFormat(LocalDateTime dt) {
return dt.format(FORMATTER); // Потокобезопасно
}

public static LocalDateTime goodParse(String str) {
return LocalDateTime.parse(str, FORMATTER);
}

//Решение 2: ThreadLocal для SimpleDateFormat (Java 7 и legacy)
private static final ThreadLocal<SimpleDateFormat> THREAD_LOCAL =
ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));

public static String threadLocalFormat(Date date) {
return THREAD_LOCAL.get().format(date);
}

// Демонстрация проблемы
public static void main(String[] args) throws InterruptedException {
ExecutorService executor = Executors.newFixedThreadPool(10);

// Плохой вариант – через несколько итераций выбросит исключение
for (int i = 0; i < 100; i++) {
executor.submit(() -> {
try {
BAD_FORMAT.parse("2024-01-01 12:00:00");
} catch (Exception e) {
System.err.println("SimpleDateFormat упал: " + e);
}
});
}

executor.shutdown();
executor.awaitTermination(1, TimeUnit.SECONDS);

// Хороший вариант – никогда не падает
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime now = LocalDateTime.now();
System.out.println("Форматирование: " + now.format(dtf));
}
}


Объяснение:
 SimpleDateFormat наследует DateFormat, который содержит Calendar – не потокобезопасный объект. Методы format и parse изменяют этот календарь, а также сбрасывают позицию парсинга. Без синхронизации два потока могут одновременно записать в одно и то же поле, что ведет к повреждению данных. 

DateTimeFormatter
 спроектирован иначе: он использует неизменяемые объекты и не хранит состояние при операциях. При форматировании он создает временные объекты, не затрагивая общий кеш. Спецификация Java 8 гарантирует потокобезопасность всех классов java.time.

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

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.CountDownLatch;

public class Task150526 {
private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

public static void main(String[] args) throws InterruptedException {
CountDownLatch latch = new CountDownLatch(2);
Runnable task = () -> {
try {
latch.await();
for (int i = 0; i < 1000; i++) {
String formatted = sdf.format(new Date());
sdf.parse(formatted);
}
} catch (Exception e) {
System.out.println("Ошибка в " + Thread.currentThread().getName() + ": " + e);
}
};

Thread t1 = new Thread(task);
Thread t2 = new Thread(task);
t1.start();
t2.start();

Thread.sleep(100);
latch.countDown();
latch.countDown();

t1.join();
t2.join();
}
}


#Tasks
👍2
Что такое Arrays класс? Какие полезные методы там есть? 🤓

Ответ:

java.util.Arrays
 — утилитный класс для работы с массивами.

Основные методы: 
sort() (сортировка массива), 
binarySearch() (бинарный поиск в отсортированном массиве), 
copyOf(), copyOfRange() (копирование), 
fill() (заполнение), 
equals() и deepEquals() (сравнение массивов, в том числе многомерных), 
toString() и deepToString() (строковое представление), 
stream() (преобразование в стрим), 
asList() (преобразование массива в список — фиксированного размера, изменения в массиве отражаются в списке и наоборот).


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

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

Пафну́тий Льво́вич Чебышёв (ошиб. Че́бышев; 4 [16] мая 1821, Окатово, Калужская губерния, Российская империя — 26 ноября [8 декабря] 1894, Санкт-Петербург, Российская империя) — русский математик и механик, основоположник петербургской математической школы, академик Петербургской академии наук и ещё 24 академий мира. Чебышёв — «величайший, наряду с Н. И. Лобачевским, русский математик XIX века». Он получил фундаментальные результаты в теории чисел (распределение простых чисел) и теории вероятностей (центральная предельная теоремазакон больших чисел), построил общую теорию ортогональных многочленов, теорию равномерных приближений и многие другие. Основал математическую теорию синтеза механизмов и разработал ряд практически важных концепций механизмов.

Йоханнес Георг Бе́днорц (нем. Johannes Georg Bednorz; род. 16 мая 1950, Нойенкирхен, ФРГ) — немецкий физик. Лауреат Нобелевской премии по физике (совместно с Александром Мюллером) в 1987 году за открытие высокотемпературной сверхпроводимости.


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

1969 — советский межпланетный космический аппарат «Венера-5» достиг планеты Венера.

2011 — Релиз компьютерной игры Terraria.

***Примерно в этот день, в игре Half-Life, происходит инцидент в исследовательском комплексе «Чёрная меза».


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

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

Леони́д (Ла́зарь) Моисе́евич Пятиго́рский (17 мая 1909, Александровка (Фундуклеевка), Киевская губерния, ныне Кировоградская область) — 12 июня 1993) — советский физик-теоретик, соавтор Л. Ландау по первому изданию первого тома фундаментального курса по теоретической физике.

Джозеф Норман Локьер (англ. Joseph Norman Lockyer; 17 мая 1836, Рагби, графство Уорикшир — 16 августа 1920, Солком-Реджис, графство Девон) — английский физик и астроном. Основатель журнала Nature и его первый редактор (на протяжении полувека, с 1869 по 1919 гг.). Норман Локьер считается пионером археоастрономии. На рубеже XIX—XX веков он изучил астрономическую ориентацию ряда монументальных сооружений Египта, Ближнего Востока, Греции и Британии и написал книгу «Заря астрономии».


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

2009 — вышла первая, тестовая версия компьютерной игры Minecraft, ставшей одной из самых популярных в мире.


#Biography #Birth_Date #Events #17мая
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Готовлю большое практическое видео по Keycloak, поэтому даже написать некогда в канал)))

А как вы проводите выходные? 🏝
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7🔥1
Keycloak с нуля: от первого токена до современной auth-архитектуры

Осваиваем Keycloak на практике: запуск, все способы аутентификации, роли, федерация, безопасность и кластеризация. Строим два Spring Boot сервиса и разбираемся, как устроена современная auth-архитектура.


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

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

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

Буду крайне благодарен
🙂
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥8
История технологии сегодня — 18 мая

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

О́ливер Хе́висайд (англ. Oliver Heaviside; 18 мая 1850 — 3 февраля 1925) — британский учёный-самоучка, инженерматематик и физик. Впервые применил комплексные числа для изучения электрических цепей, разработал технику применения преобразования Лапласа для решения дифференциальных уравнений, переформулировал уравнения Максвелла в терминах трёхмерных векторов, напряжённостей электрического и магнитного полей и электрической и магнитной индукций, и, независимо от других математиков, создал векторный анализ. Несмотря на то, что Хевисайд большую часть жизни был не в ладах с научным сообществом, его работы изменили облик математики и физики.


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

1888 — в США впервые продемонстрирована первая граммофонная пластинка.

1923 — французский инженер Антуан Барнай (Antoine Barnay) получил патент на телефон с дисковым набором номера.


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

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

Параметризованные сообщения SLF4J: почему это лучше конкатенации строк

Конкатенация строк через оператор + внутри вызова логгера кажется безобидной, но порождает скрытые накладные расходы. Компилятор Java транслирует выражение "User " + userId + " not found" в создание объекта StringBuilder, последовательный вызов append для каждого операнда и финальный toString. Если такая операция выполняется внутри цикла или при высокой нагрузке, каждый вызов порождает несколько объектов в heap, увеличивая давление на garbage collector.

Критический недостаток проявляется при отключенном уровне логирования.

Предположим, корневой уровень установлен на INFO, а в коде присутствует:
logger.debug("User " + userId + " not found in database " + dbName + " after " + duration + "ms");


Несмотря на то что сообщение не будет выведено, конкатенация выполняется безусловно. JVM создает StringBuilder, четыре промежуточных строки и финальный результат — все это немедленно становится мусором. В hot path с тысячами вызовов в секунду такие бесполезные аллокации приводят к учащению minor GC и деградации latency.


Механизм параметризованных сообщений

SLF4J предоставляет перегруженные методы с шаблоном и переменным числом аргументов:
logger.debug("User {} not found in database {} after {}ms", userId, dbName, duration);


Здесь {} — placeholder, который заменяется на строковое представление аргумента. Ключевое отличие: подстановка выполняется внутри реализации логгера, и только если уровень DEBUG активен. Если уровень отключен, метод завершается после проверки флага, не трогая аргументы и не создавая результирующей строки.

Внутри Logback это реализовано через MessageFormatter. Класс FormattingTuple выполняет ленивую сборку сообщения, обходя аргументы массивом только при фактической необходимости записи. Для одного и двух аргументов SLF4J предоставляет оптимизированные перегрузки, избегая создания массива объектов:
// Оптимизированные перегрузки для 1-2 аргументов без varargs
public void debug(String format, Object arg);
public void debug(String format, Object arg1, Object arg2);
public void debug(String format, Object... arguments); // 3+



Производительность: измеримая разница

Разница между конкатенацией и параметризации критична именно при отключенном уровне. Если DEBUG включен, оба подхода создают строку, и издержки сопоставимы. Но в production, где DEBUG обычно отключен, параметризованный вызов сводится к одной проверке булева флага и немедленному возврату.

Рассмотрим микробенчмарк-логику. Конкатенация при отключенном DEBUG:
// Всегда выполняется: StringBuilder + 4 append + toString
logger.debug("User " + userId + " not found");


Параметризация при отключенном DEBUG:
// SLF4J: проверка isDebugEnabled() внутри, немедленный return
logger.debug("User {} not found", userId);


Второй вариант на порядки быстрее и не порождает мусора. Это особенно важно для логирования в циклах обработки коллекций или при логировании состояния каждого элемента в batch-операции.


#Java #для_новичков #beginner #logging #Log4j2 #Logback #SLF4J
👍5