Easy Java
4.96K subscribers
317 photos
51 videos
469 links
Лучшие обучающие материалы и другие полезности для Java-разработчиков.

Сотрудничество: @heywan_n1

Цены: @heywan_media

Реклама на бирже: https://telega.in/c/+r8kkGSypBY84MmIy
Download Telegram
👩‍💻 Качество кода в эпоху AI: как не утонуть в багах и уязвимостях

Автор разбирает, почему внедрение AI может снижать продуктивность, раздувать время ревью и плодить уязвимости. И главное — как это лечить не магическими промптами, а инженерным пайплайном: SDD, TDD, узкие AI-ревьюеры, property-based testing и связка LLM с формальными анализаторами.

⛓ Читаем статью по ссылке

➡️ Easy Java | #Статья
Please open Telegram to view this post
VIEW IN TELEGRAM
❤3
👩‍💻 Викторина: что выведет код?

class Parent {
static String show() {
return "Parent";
}

String print() {
return show();
}
}

class Child extends Parent {
static String show() {
return "Child";
}
}

public class Main {
public static void main(String[] args) {
Parent p = new Child();
System.out.println(p.print());
}
}


➡️ Easy Java | #Викторина
Please open Telegram to view this post
VIEW IN TELEGRAM
😁6🤔2🔥1
👩‍💻 Что такое ThreadLocal.withInitial() и зачем он нужен?

Это статический метод для создания ThreadLocal переменной с фабрикой начального значения. Каждый поток получает свою собственную копию объекта, а withInitial задаёт ленивый способ её создания — при первом вызове get().

⚡️ Пример:

import java.text.SimpleDateFormat;
import java.util.concurrent.*;

public class ThreadLocalExample {
// Безопасный форматтер без синхронизации
private static final ThreadLocal<SimpleDateFormat> dateFormat =
ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd"));

public static void main(String[] args) throws Exception {
ExecutorService pool = Executors.newFixedThreadPool(3);

for (int i = 0; i < 5; i++) {
final int taskId = i;
pool.submit(() -> {
String formatted = dateFormat.get().format(new java.util.Date());
System.out.println(Thread.currentThread().getName() + " -> " + formatted + " (task " + taskId + ")");
});
}

pool.shutdown();
}
}


Особенно полезен при хранении не потокобезопасных объектов (SimpleDateFormat, Random), изоляции пользовательской сессии/токена в вебе, переиспользовании тяжелых ресурсов без синхронизации.


➡️ Easy Java | #Теория
Please open Telegram to view this post
VIEW IN TELEGRAM
⚡1
Ну, а как по другому…

➡️ Easy Java | #мем
Please open Telegram to view this post
VIEW IN TELEGRAM
👩‍💻 A2A Java SDK 1.0.0: стабильный релиз для агентных приложений на Java

Официальный Java SDK для протокола Agent2Agent достиг версии 1.0.0. Теперь Java-разработчики могут строить агентные приложения, которые взаимодействуют с агентами на других языках и фреймворках.

Agent2Agent — это протокол, управляемый Linux Foundation (изначально представленный Google), который позволяет агентам на разных фреймворках и языках находить друг друга, делегировать задачи и обмениваться результатами.

⛓ Подробнее в статье

➡️ Easy Java | #Статья
Please open Telegram to view this post
VIEW IN TELEGRAM
👩‍💻 Викторина: что выведет код?

class Parent {
static int a = initA();

static int initA() {
System.out.print("P ");
return 1;
}

Parent() {
System.out.print("p ");
}
}

class Child extends Parent {
static int b = initB();

static int initB() {
System.out.print("C ");
return 2;
}

Child() {
System.out.print("c ");
}
}

public class Main {
public static void main(String[] args) {
new Child();
}
}

➡️ Easy Java | #Викторина
Please open Telegram to view this post
VIEW IN TELEGRAM
👩‍💻 Что такое ReentrantReadWriteLock в Java и зачем он нужен?

ReentrantReadWriteLock — это улучшенная альтернатива synchronized, позволяющая одновременно выполнять несколько чтений, но блокировать доступ на запись.

Он состоит из двух независимых замков:
• readLock() — совместимый, позволяет многим потокам читать параллельно
• writeLock() — эксклюзивный, разрешает только одному потоку писать


⚡️ Пример:

import java.util.concurrent.locks.*;

public class Main {
private static final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
private static int value = 0;

public static void main(String[] args) {
Runnable reader = () -> {
lock.readLock().lock();
try {
System.out.println("Чтение: " + value);
} finally {
lock.readLock().unlock();
}
};

Runnable writer = () -> {
lock.writeLock().lock();
try {
value++;
System.out.println("Запись: " + value);
} finally {
lock.writeLock().unlock();
}
};

new Thread(reader).start();
new Thread(writer).start();
}
}


👀 ReentrantReadWriteLock особенно полезен, когда чтений гораздо больше, чем записей — например, в кэшах, справочниках или аналитических сервисах


➡️ Easy Java | #Теория
Please open Telegram to view this post
VIEW IN TELEGRAM
ㅤ
Страх.
Гнев.
Стыд.
Вина.
Тревога.
Апатия.
Уныние.
Изоляция.
Бессилие.

Контакт.
Тепло.
Чувство.
Живость.
Ясность.
Точность.
Присутствие.
Тишина.

Покой.

Если выбор сделан,
твоё место здесь:

мэверик

Входи осторожно.

Кислород
зашкаливает.
ㅤ
🤡5🤣2
👩‍💻 Что такое Collectors.partitioningBy() и зачем он нужен?

Collectors.partitioningBy() — это коллектор из Java Stream API, который разделяет элементы потока на две группы (true/false) на основе заданного предиката, возвращая Map<Boolean, List<T>>.

⚡️ Пример:
import java.util.*;
import java.util.stream.*;
import java.util.function.Predicate;

public class PartitioningByExample {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

// Разделение чисел на четные и нечетные
Map<Boolean, List<Integer>> partitioned = numbers.stream()
.collect(Collectors.partitioningBy(n -> n % 2 == 0));

System.out.println("Четные: " + partitioned.get(true)); // [2, 4, 6, 8, 10]
System.out.println("Нечетные: " + partitioned.get(false)); // [1, 3, 5, 7, 9]

// Строки по длине
List<String> words = Arrays.asList("яблоко", "груша", "слива", "апельсин", "лимон");

Map<Boolean, List<String>> byLength = words.stream()
.collect(Collectors.partitioningBy(word -> word.length() > 5));

System.out.println("\nКороткие слова (≤5 букв): " + byLength.get(false));
System.out.println("Длинные слова (>5 букв): " + byLength.get(true));

// С дополнительным коллектором - подсчет количества
Map<Boolean, Long> countPartition = numbers.stream()
.collect(Collectors.partitioningBy(
n -> n > 5,
Collectors.counting()
));

System.out.println("\nЧисел ≤5: " + countPartition.get(false));
System.out.println("Чисел >5: " + countPartition.get(true));
}
}


👀 Особенно полезен для разделения данных на прошедшие/не прошедшие валидацию, категоризации на успешные/ошибочные операции, статистического анализа.


➡️ Easy Java | #Теория
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8❤3🔥2
👩‍💻 Что такое Exchanger в Java и зачем он нужен?

Exchanger — это синхронизатор из пакета java.util.concurrent, который позволяет двум потокам обмениваться данными в точке встречи. Каждый поток вызывает метод exchange(), и когда оба потока доходят до этой точки, они обмениваются переданными объектами.

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


• Позволяет безопасно обмениваться объектами между потоками
• Подходит для реализации producer-consumer моделей
• Удобен для синхронных этапов вычислений

⚡️ Пример:

import java.util.concurrent.Exchanger;

public class Main {
public static void main(String[] args) {
Exchanger<String> exchanger = new Exchanger<>();

Runnable producer = () -> {
try {
String data = "Данные от Producer";
System.out.println("Producer отправил: " + data);
String response = exchanger.exchange(data);
System.out.println("Producer получил: " + response);
} catch (InterruptedException e) {
e.printStackTrace();
}
};

Runnable consumer = () -> {
try {
String data = "Ответ от Consumer";
System.out.println("Consumer отправил: " + data);
String received = exchanger.exchange(data);
System.out.println("Consumer получил: " + received);
} catch (InterruptedException e) {
e.printStackTrace();
}
};

new Thread(producer).start();
new Thread(consumer).start();
}
}


👀 Exchanger особенно полезен, когда два потока выполняют разные задачи и должны регулярно обмениваться результатами — например, генератор данных и обработчик, или два этапа сложного расчёта.


➡️ Easy Java | #Теория
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2🔥2❤1
⚡️⚡️Joker 2026: что происходит с профессией разработчика

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

Поэтому в этом сезоне меняется и Joker: первый день традиционно посвящен Java — Core Java, рантайму и работе на уровне железа. А во второй день будем обсуждать, как прямо сейчас меняется сама инженерная практика.

В программе — Context Engineering, команды из людей и ИИ-агентов, Self-Evolving Agents, новые подходы к архитектуре и работе с моделями, а также вопросы ответственности и роли эксперта.

Собрали главные темы второго дня в карточках.

🌟С промокодом: EasyJava23 персональные билеты дешевле

Полное расписание и билеты — на сайте.
❤2👍1🔥1