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
Готовлю большое практическое видео по 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
Guard-методы и параметризация

До появления широкого использования SLF4J распространенным паттерном был явной guard:
if (logger.isDebugEnabled()) {
logger.debug("User " + userId + " not found");
}

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

Guard остается оправдан только при дорогостоящем вычислении аргумента:
// Аргумент требует сериализации — guard необходим
if (logger.isDebugEnabled()) {
logger.debug("Full state: {}", objectMapper.writeValueAsString(complexObject));
}


Здесь даже параметризация не спасет, потому что writeValueAsString выполняется до вызова логгера как частичное вычисление аргумента. SLF4J не может отложить выполнение произвольного выражения.


Исключения и параметризация

Особый случай — логирование исключений. SLF4J распознает последний аргумент типа Throwable и обрабатывает его отдельно от параметров:
// Правильно: throwable логируется со стектрейсом
logger.error("Payment {} failed for user {}", paymentId, userId, exception);

// Неправильно: исключение превращается в toString(), стектрейс потерян
logger.error("Payment " + paymentId + " failed: " + exception.getMessage());

В параметризованном вызове последний Throwable не подставляется в шаблон, а передается в appender для вывода полного стектрейса. При конкатенации разработчик часто ограничивается exception.getMessage(), теряя критически важную информацию о месте возникновения и цепочке вызовов.


#Java #для_новичков #beginner #logging #Log4j2 #Logback #SLF4J
👍5
Напоминаю, что набираю на обучение желающих погрузиться в мир Java! 🤓

Пишите в лс @Oleborn, все обсудим. 😉
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
Что выведет код?

public class Task180526 {
public static void main(String[] args) {
String a = "hello";
String b = "world";
String c = a + b;
String d = "hello" + "world";

System.out.println(c == d);
System.out.println(c.intern() == d);
System.out.println((a + b).intern() == d);
}
}


#Tasks
👍3
👍4
Что такое System.arraycopy()? Чем отличается от Arrays.copyOf() 🤓

Ответ:

System.arraycopy() — это нативный метод, выполняющий быстрое копирование элементов из одного массива в другой.

Параметры: исходный массив, начальная позиция в нем, целевой массив, начальная позиция в нем, количество копируемых элементов.

Важно: целевой массив должен существовать и иметь достаточный размер. 

Arrays.copyOf() — более высокоуровневый метод, который создает новый массив внутри себя, используя System.arraycopy(). Также позволяет изменить длину копии (обрезать или дополнить значениями по умолчанию).


#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
Готовлю новую статью))

Как считаете не слишком пафосно и кликбейтно? 😂😂😂

Но я все равно поржал от генераторов картинок😂😂😂
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🔥2
История технологии сегодня — 19 мая

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

Гэри Арлен Килдалл (19 мая 1942, Сиэтл, Вашингтон — 11 июля 1994, Монтерей, Калифорния) — программист и предприниматель, создавший операционную систему CP/M и основавший Digital Research, Inc. (DRI). Килдалл был одним из первых, кто увидел потенциал микропроцессоров не только в качестве контроллеров оборудования, но и как часть мощного персонального компьютера.


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

1910 — возвращение кометы ГаллеяЗемля пересекла хвост кометы.

1980 - в Анахайме, Калифорния, Apple представил публике свою новую разработку — компьютер «Apple III». Это стало первой неудачей известной фирмы.


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

Тема: String.split() принимает регулярное выражение.

Проблема: Метод String.split(String regex) интерпретирует аргумент как регулярное выражение (regex), а не как литеральную строку. Символ точки (.) в regex означает "любой символ". Поэтому вызов "a.b.c".split(".") разделит строку по каждому символу, а не по точкам, вернув пустой массив. Аналогичные проблемы возникают с другими спецсимволами: $|*+?^()[{.

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

Решение: Используйте Pattern.quote() для экранирования всей строки или экранируйте отдельные символы двойным обратным слешем (\\.\\|). Для простых односимвольных разделителей можно использовать split(Pattern.quote(".")). Если разделитель не является regex-спецсимволом (например, запятая или пробел), экранирование не требуется.

Альтернативно, используйте StringUtils.split() из Apache Commons Lang, который работает с литералами.
public class StringSplitRegex {

public static void main(String[] args) {
String ip = "192.168.1.1";
String csv = "a|b|c";
String math = "10*20*30";

//Антипаттерн: без экранирования
String[] badSplit = ip.split(".");
System.out.println("split(\".\") length: " + badSplit.length); // 0
// Регулярка '.' совпала с каждым символом, результат пустой

String[] badPipe = csv.split("|");
System.out.println("split(\"|\") length: " + badPipe.length); // 7
// '|' в regex означает "или" — результат каждый символ

//Решение 1: экранирование двойным слешем
String[] goodDot = ip.split("\\.");
System.out.println("split(\"\\\\.\") : " + String.join(", ", goodDot));

String[] goodPipe = csv.split("\\|");
System.out.println("split(\"\\\\|\") : " + String.join(", ", goodPipe));

//Решение 2: Pattern.quote() — экранирует всё
String[] quoted = ip.split(Pattern.quote("."));
System.out.println("Pattern.quote(\".\") : " + String.join(", ", quoted));

//Решение 3: для сложных случаев — ограничение на количество частей
String[] limited = "one:two:three:four".split(":", 3);
System.out.println("split with limit: " + String.join(", ", limited)); // [one, two, three:four]

// Альтернатива: ручная работа без regex
String[] manual = "one,two,three".split(",", -1); // -1 сохраняет пустые хвосты
System.out.println("Manual: " + String.join(", ", manual));

// Внимание: обратный слеш требует четыре слеша в Java
String path = "C:\\Users\\Name\\file.txt";
String[] pathParts = path.split("\\\\"); // \\\\ экранирует один \
System.out.println("Path parts: " + String.join(" | ", pathParts));
}
}


Объяснение:
 Регулярные выражения используют множество метасимволов.

Точка (.) — самый частый подвох. Двойной обратный слеш (\\.) нужен потому, что Java требует экранирования обратного слеша в строковом литерале: первый слеш экранирует второй, и в regex передается \., что означает "буквальная точка". 

Pattern.quote()
 автоматически добавляет \Q и \E вокруг строки, что указывает regex-движку интерпретировать содержимое буквально. Это наиболее безопасный способ при динамических разделителях. Параметр limit в split() управляет количеством частей: отрицательное значение сохраняет пустые строки в конце, ноль (по умолчанию) — удаляет.


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

import java.util.Arrays;

public class Task190526 {
public static void main(String[] args) {
String str = "1.2.3.";
String[] parts = str.split(".");
System.out.println(parts.length);
System.out.println(Arrays.toString(parts));
}
}


#Tasks
👍2
Варианты ответа:
Anonymous Quiz
20%
4 [1, 2, 3]
35%
4 [1, 2, 3, ]
45%
0 []
0%
1 [1.2.3.]
👍4
Итак ребят. Новая статья. 💃

С пылу с жару. Специально для вас)))

Оцениваем
🙂
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7
Что такое CAS (Compare-And-Swap) операции? 🤓

Ответ:

CAS — это атомарная инструкция процессора, которая сравнивает значение в памяти с ожидаемым значением, и если они равны, заменяет его на новое.

Выполняется атомарно (одна инструкция).

В Java CAS реализован через sun.misc.Unsafe и используется в атомарных классах (AtomicInteger, AtomicLong, AtomicReference) и в ConcurrentHashMap.

CAS — основа неблокирующих (lock-free) алгоритмов, которые работают быстрее synchronized при низкой конкуренции, так как не переводят поток в режим ожидания.


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

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

Исаа́к (Ю́зик) Я́ковлевич Померанчу́к (7 (20) мая 1913, Варшава — 14 декабря 1966, Москва) — советский физик-теоретикакадемик АН СССР (1964; член-корреспондент 1953).

Уильям Реддингтон Хьюлетт (англ. William Reddington Hewlett, 20 мая 1913 — 12 января 2001) — американский инженер, соучредитель компании «Hewlett-Packard» (HP, вместе с Дэвидом Паккардом).

Эмиль Берлинер (англ. Emile Berliner; 20 мая 1851, Ганновер — 3 августа 1931, Вашингтон) — американский изобретатель граммофона и микрофона, конструктор летательных аппаратов и общественный деятель.


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

1891 — изобретатель Томас Эдисон показал общественности кинетоскоп, машину движущегося изображения.

1977 — первый полёт советского истребителя четвёртого поколения Су-27.



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

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

Логирование исключений — правильная передача throwable последним параметром

SLF4J анализирует последний аргумент метода логирования. Если он является экземпляром java.lang.Throwable, фреймворк обрабатывает его отдельно от параметров подстановки: исключение передается в appender для вывода полного стектрейса, а не встраивается в текст сообщения через {}.
// Правильно: throwable — последний параметр, SLF4J выведет стектрейс
logger.error("Payment processing failed for order {}", orderId, exception);

Здесь orderId подставляется в {}, а exception передается как объект Throwable. Logback или Log4j2 извлекают из него класс, сообщение и полный стектрейс, форматируя их согласно layout-конфигурации.
Механизм работает для любого количества параметров.

При одном аргументе-исключении и отсутствии placeholder-ов SLF4J использует сообщение исключения как текст лога и дополняет его стектрейсом:
// SLF4J интерпретирует exception как Throwable, а не как параметр подстановки
logger.error("Database connection lost", exception);



Проблема logger.error(e.getMessage(), e)

Этот паттерн встречается в коде, где разработчик хочет, чтобы текст лога совпадал с сообщением исключения.

Однако он порождает несколько проблем:
Дублирование сообщения. Если layout настроен на вывод %ex или %exception, стектрейс начинается с имени класса исключения и его getMessage(). Таким образом, сообщение исключения появляется дважды: в заголовке лога и в начале стектрейса.
// Вывод при logger.error(e.getMessage(), e)
2024-01-15 10:23:14 ERROR Connection timeout after 30000ms
java.net.SocketTimeoutException: Connection timeout after 30000ms
at java.net.SocketInputStream.socketRead0(Native Method)
...

Первая строка повторяет содержимое второй, увеличивая объем лога без добавления информации.

Потеря контекста. e.getMessage() часто содержит только техническое описание, лишенное бизнес-контекста. Сравните:
// Антипаттерн: что за заказ? какой шлюз?
logger.error(e.getMessage(), e);

// Правильно: контекст в сообщении, детали в стектрейсе
logger.error("Payment failed for order {} via gateway {}", orderId, gatewayId, e);


Риск null-сообщения.
Не все исключения имеют непустое сообщение. NullPointerException без кастомного сообщения вернет null, и logger.error(null, e) приведет к неинформативной строке null в заголовке лога.

Невозможность параметризации. Форма logger.error(e.getMessage(), e) не позволяет добавить параметры контекста, так как место для {} занято самим сообщением исключения.


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