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
История технологии сегодня — 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
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