Java | Фишки и трюки
7.21K subscribers
182 photos
29 videos
6 files
40 links
Java: примеры кода, интересные фишки и полезные трюки

Купить рекламу: https://telega.in/c/java_tips_and_tricks

✍️По всем вопросам: @Pascal4eg
Download Telegram
☕️ Хватит писать циклы! Java 8 дала тебе больше

С 8-й версии Java предлагает мощные инструменты для работы с коллекциями — и пора ими воспользоваться. Забудь про for и while, когда можно писать элегантно и декларативно.

В статье ты найдёшь:
📌 10 лучших методов из Stream API, которые экономят строки кода
📌 Как заменить громоздкие циклы одной строкой
📌 Примеры filter(), map(), collect() и других трюков
📌 Объяснение, почему функциональный стиль — это не боль, а кайф
📌 Практические сценарии: фильтрация, преобразование, группировка, подсчёты

➡️ Читайте и наслаждайтесь

🗣️ Пиши меньше, делай больше. Stream API — must-have для современного джависта.

🤩 Java Фишки и трюки || #Cтатья
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥82❤‍🔥2👍2
🌐 WebClient — современная замена RestTemplate в Java


RestTemplate давно знаком, но теперь Spring рекомендует использовать WebClient. Это не просто новый способ сделать HTTP-запросы — это полноценный инструмент, который умеет работать асинхронно, поддерживает реактивность и даёт гораздо больше контроля над процессом.

Вот как выглядит простой GET-запрос:
WebClient client = WebClient.create();

String body = client.get()
.uri("https://api.github.com/users/octocat")
.retrieve()
.bodyToMono(String.class)
.block();

System.out.println(body);

Здесь bodyToMono(String.class) возвращает реактивный тип Mono, который содержит результат. Если вызвать .block(), запрос будет выполняться синхронно, так что можно легко внедрять WebClient даже в привычный код.

Для POST-запроса с телом используем:

WebClient client = WebClient.create("https://httpbin.org");

String response = client.post()
.uri("/post")
.header("Content-Type", "application/json")
.bodyValue("{\"name\":\"PyLinux\"}")
.retrieve()
.bodyToMono(String.class)
.block();

System.out.println(response);


Ошибки обрабатываются через onStatus, например, для 4xx:
client.get()
.uri("https://api.github.com/404")
.retrieve()
.onStatus(status -> status.is4xxClientError(), resp -> {
System.out.println("Ошибка клиента: " + resp.statusCode());
return Mono.error(new RuntimeException("Client error"));
})
.bodyToMono(String.class)
.block();


Если нужно передать заголовки или параметры:
WebClient client = WebClient.builder()
.baseUrl("https://api.example.com")
.defaultHeader("Authorization", "Bearer your_token")
.build();

String data = client.get()
.uri(uriBuilder -> uriBuilder
.path("/data")
.queryParam("limit", 10)
.build())
.retrieve()
.bodyToMono(String.class)
.block();


Таким образом, WebClient позволяет легко делать запросы с любыми параметрами и заголовками, при этом можно управлять асинхронностью и реактивностью без лишних сложностей.


🗣️ Запомни: WebClient — это не просто новый класс. Это современный подход к HTTP в Java, который ты сможешь использовать и в обычных приложениях, и в реактивных. Если хочешь гибкости и мощи — забудь про RestTemplate и сразу учись WebClient.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍104❤‍🔥3💅2🔥1
Media is too big
VIEW IN TELEGRAM
☕️ Что такое Project Loom?

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


🤩 Java Фишки и трюки || #Видео
Please open Telegram to view this post
VIEW IN TELEGRAM
👍21🔥1
☕️ List.of() в Java — быстро, но не всегда безопасно

С Java 9 появился удобный способ создать список:
List<String> names = List.of("Alice", "Bob", "Charlie");

Выглядит лаконично, работает быстро — но есть нюанс.

⚠️ Подводные камни

1️⃣.📛 Список неизменяемый
List<String> list = List.of("a", "b");
list.add("c"); // 💥 UnsupportedOperationException
list.remove("a"); // 💥 тоже ошибка

Любая попытка изменить список — ошибка во время выполнения. Это не ArrayList, а immutable List.

2️⃣.💣 Нельзя null
List<String> list = List.of("hello", null);  // 💥 NullPointerException

Даже один null — и всё падает. Потому что List.of() не допускает null ни в одном элементе.

3️⃣.🎭 Не всегда List, который ты ожидаешь
System.out.println(List.of("a", "b").getClass());
// class java.util.ImmutableCollections$ListN

Это не ArrayList, не LinkedList. Это внутренний тип, оптимизированный под неизменяемость.

Если твой код ждёт ArrayList и будет кастить — ловишь ClassCastException.

🧪 Где безопасно использовать:

🟢 Константные списки (List.of(DAYS))
🟢 Аргументы в методах, где ничего не модифицируется
🟢 Когда 100% уверен, что null нет

Альтернатива с возможностью изменения:
List<String> modifiable = new ArrayList<>(List.of("a", "b", "c"));
modifiable.add("d"); // 👍 теперь можно


🗣️ Запомни: List.of() — круто для коротких, неизменяемых данных.
Но если планируешь менять список или есть шанс на nullлучше явно используй `ArrayList`.
Не пались на удобстве — знай, что лежит под капотом.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥135
🧵 Используй try-with-resources с потоками правильно (и продвинуто)

Если ты до сих пор закрываешь потоки руками или думаешь, что try-with-resources — это только для файлов, смотри:

🛠 Пример 1: чтение и закрытие автоматически
try (BufferedReader reader = Files.newBufferedReader(Path.of("data.txt"))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
}


☑️ Поток закрывается автоматически — даже если внутри случится исключение.


🧪 Пример 2: кастомный ресурс (любой AutoCloseable)
public class TempResource implements AutoCloseable {
public void doSomething() {
System.out.println("Работаем с ресурсом");
}

@Override
public void close() {
System.out.println("Ресурс закрыт");
}
}

try (TempResource res = new TempResource()) {
res.doSomething();
}

🧠 Всё, что реализует AutoCloseable, можно оборачивать в try-with-resources. Это не только файлы, но и сетевые соединения, стримы, логи, сессии Hibernate и др.

🕸 Пример 3: несколько ресурсов
try (
InputStream in = new FileInputStream("input.txt");
OutputStream out = new FileOutputStream("output.txt")
) {
in.transferTo(out);
}

🔒 Все ресурсы закроются в обратном порядке.


🗣️ Запомни: try-with-resources — не просто синтаксический сахар. Это способ писать надёжный код без утечек ресурсов и без лишнего шаблонного кода. Особенно полезно при работе с сетью, файлами, базами данных и внешними API.
Please open Telegram to view this post
VIEW IN TELEGRAM
8👍6🔥4
🧠 Java и AI: как использовать LangChain4J в 2025

Считаешь Java не для AI? Серьёзно ошибаешься! LangChain, фреймворк для разработки с языковыми моделями, теперь уже доступен и для Java — через LangChain4J.

В статье ты узнаешь:

📌 Как использовать LangChain4J для создания цепочек запросов с LLM
📌 Взаимодействие с векторными хранилищами и RAG
📌 Примеры кода на Java для NLP-задач
📌 Почему Java‑специалистам уже пора в AI

➡️ Читайте и наслаждайтесь

🗣️ Java всё ближе к языкам будущего. Попробуй новое направление уже сейчас!

🤩 Java Фишки и трюки || #Cтатья
Please open Telegram to view this post
VIEW IN TELEGRAM
👍42🔥2👏1
🌀 Pattern Matching в Java — прощай `instanceof + cast`

Раньше, чтобы проверить тип и привести его, писали вот так:
if (obj instanceof String) {
String s = (String) obj;
System.out.println(s.toLowerCase());
}

👎 Шумно, опасно, повторяется.

С Java 16+ можно проще и безопаснее — паттерн-матчинг для `instanceof`:

✔️ Как это работает:
if (obj instanceof String s) {
System.out.println(s.toLowerCase());
}

Если objString, то переменная s уже приведена к нужному типу.
Больше никаких ручных кастов.

🛠 Примеры на практике:

☑️ Проверка нескольких типов
void printInfo(Object obj) {
if (obj instanceof String s) {
System.out.println("Строка: " + s.toUpperCase());
} else if (obj instanceof Integer i) {
System.out.println("Число: " + (i * 2));
} else {
System.out.println("Что-то другое");
}
}

🔍 Код стал чище: без каста, без дублирования obj.

🚀 Использование внутри switch

С Java 21 (preview) можно использовать switch с типами:
static String format(Object obj) {
return switch (obj) {
case String s -> "Строка: " + s;
case Integer i -> "Целое: " + i;
case null -> "null";
default -> "Неизвестно";
};
}

➡️ Это называется Pattern Matching for switch.

🧩 Совмещение с guard'ами
if (obj instanceof String s && s.length() > 5) {
System.out.println("Длинная строка: " + s);
}

⚠️ s будет доступна только если оба условия выполняются. Это безопасно.

🧪 Более сложные условия
if (!(obj instanceof String s)) return;
System.out.println("Обрабатываем строку: " + s.toLowerCase());

Можно комбинировать с !instanceof, return, continue, break и др.

🗣️ Запомни: Используй instanceof с привязкой переменной — особенно в if-else, парсерах, логике обработки событий и switch.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍133🔥2👨‍💻1
🚀 Java Stream API: продвинутые приёмы и подводные камни

Stream API — мощный инструмент, но легко попасть в ловушку, если не знать нюансов.

Фишки, которые нужно знать

🟢 Фильтрация и преобразование в одну строку:
List<String> names = users.stream()
.filter(u -> u.isActive())
.map(User::getName)
.collect(Collectors.toList());


🟢 Собрать в Map без дублирующих ключей:
Map<Long, String> map = users.stream()
.collect(Collectors.toMap(
User::getId,
User::getName,
(a, b) -> a // если дубликат — оставить первый
));


🟢 Группировка и сортировка:
Map<String, List<User>> grouped = users.stream()
.collect(Collectors.groupingBy(User::getRole));


⚠️ Подводные камни

🟢 Не перезапускается!
Stream<String> stream = list.stream();
stream.forEach(System.out::println);
// stream.forEach(...) // выбросит исключение — уже использован


🟢 Ленивая природа:
Stream.of("a", "b", "c")
.filter(s -> {
System.out.println("filter: " + s);
return true;
});
// ничего не произойдёт, пока не вызвать .collect() или .forEach()


🟢 Null внутри Stream — плохая идея:
Stream.of("a", null, "b");  //  NPE при map/filter


Лучше фильтровать:
Stream.of("a", null, "b")
.filter(Objects::nonNull)
.map(String::toUpperCase)
.forEach(System.out::println);


🔍 Продвинутый пример

Фильтруем активных, сортируем по дате, берём 10 последних:
List<Post> recent = posts.stream()
.filter(Post::isActive)
.sorted(Comparator.comparing(Post::getCreatedAt).reversed())
.limit(10)
.collect(Collectors.toList());


🗣️ Запомни: Stream API — кайф, если понимаешь, что делаешь.
Всегда помни про однократность, лень и null — и всё будет летать.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍156🔥2❤‍🔥1
⚙️ Оптимизация Collections и Stream API — как это делать профессионально

Используешь Stream в Java 8+? Только не думай, что это всегда просто и быстро. В этой статье — реальные кейсы и трюки, которые позволят ускорить обработку коллекций и избежать типичных ошибок.

В статье ты узнаешь:

📌 Лучшие приёмы работы со Stream, чтобы избежать лишней аллокации
📌 Когда Stream быстрее цикла, а когда цикл — всё же король производительности
📌 Практические советы: избегать лишних объектов, использовать правильные методы сборки
📌 Ускорение благодаря профайлингу и тому, как выжать максимум из JIT

➡️ Читайте и наслаждайтесь

🗣️ Java всегда сильна в коллекциях — сделай свой код быстрее и чище уже сегодня!

🤩 Java Фишки и трюки || #Cтатья
Please open Telegram to view this post
VIEW IN TELEGRAM
👍31
💎 Clean Code на Java — идиоматические приёмы, которые реально работают

Хочешь писать Java-код, который приятно читать и легко сопровождать?
Вот не теория с книжек, а настоящие идиомы, шаблоны и фишки, которые делают код чистым, понятным и «живым».

👍 1. Именование — полдела

Плохо:
double d = get(a, b);


✔️Лучше:
double distance = calculateDistance(startPoint, endPoint);

Именуй переменные и методы так, чтобы код сам говорил, что он делает.

👍 2. if без else — код легче читать

Было:
if (isAdmin) {
grantAccess();
} else {
denyAccess();
}


✔️ Стало:
if (!isAdmin) {
denyAccess();
return;
}
grantAccess();


Меньше вложенности → легче читать.

👍 3. Меньше булевых флагов

Неочевидно:
public void start(boolean silent) {
if (!silent) {
System.out.println("Starting...");
}
// ...
}


✔️ Читаемо:
public void startLoud() {
System.out.println("Starting...");
start();
}

public void start() {
// ...
}

Выноси поведение в отдельные методы, а не в булевы флаги.

👍 4. Используй Optional вместо null

Потенциальный NPE:
String name = user.getName();


✔️ Безопаснее:
Optional<String> name = user.getNameOptional();
name.ifPresent(System.out::println);

Optional показывает, что значение может отсутствовать.

👍 5. Выражай намерение через enum

Магические числа:
send(2);


✔️ Ясно:
send(Priority.HIGH);

enum передаёт смысл.

👍 6. Строим объекты читаемо: builder

Плохо читается:
User u = new User("Ann", 25, true, "Russia", null, false);


✔️ Круто:
User user = User.builder()
.name("Ann")
.age(25)
.active(true)
.country("Russia")
.build();

Именованные параметры через builder — читабельность x10.

👍 7. Используй switch-expression в Java 14+

Старый подход:
int days;
switch (month) {
case JANUARY: days = 31; break;
case FEBRUARY: days = 28; break;
// ...
}


✔️ Современный:
int days = switch (month) {
case JANUARY, MARCH, MAY -> 31;
case FEBRUARY -> 28;
default -> throw new IllegalArgumentException();
};

Чётко, лаконично, без лишнего кода.

👍 8. Чистые методы = маленькие и простые

Монстр:
public void registerUser(UserDto dto) {
validate(dto);
saveToDatabase(dto);
sendWelcomeEmail(dto);
logRegistration(dto);
}


✔️ Разбиваем:
public void registerUser(UserDto dto) {
validate(dto);
persist(dto);
notify(dto);
}

private void validate(UserDto dto) { ... }
private void persist(UserDto dto) { ... }
private void notify(UserDto dto) { ... }

Каждый метод делает одну вещь. Легко тестировать, легко читать.

👍 9. Предпочитай Streams + map/filter/collect

Старый for:
List<String> active = new ArrayList<>();
for (User u : users) {
if (u.isActive()) {
active.add(u.getName().toUpperCase());
}
}


✔️ Современно:
List<String> active = users.stream()
.filter(User::isActive)
.map(u -> u.getName().toUpperCase())
.collect(Collectors.toList());

Чисто, выразительно, без шума.

👍 10. Старайся не ловить Exception без причины

Так себе:
try {
Thread.sleep(100);
} catch (Exception e) {
// игнорируем
}


✔️ Так лучше:
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException(e);
}

Нельзя просто проглатывать ошибки — это превращается в хаос.


🗣️ Запомни:
Clean code — это не строгость, а удобство.

Читаемый код — это код, который ты поймёшь через 3 месяца в 2 часа ночи.
Не бойся переписывать, выносить, называть по-человечески — в этом сила Java-разработчика.
Please open Telegram to view this post
VIEW IN TELEGRAM
11👍7🔥4❤‍🔥2👎2🥰1💯1
🧵 Virtual Threads (Project Loom) — тысячи потоков без overhead’а

Хочешь запускать 10 000 параллельных задач в Java без боли с thread pool?
Теперь можно — с virtual threads. Это не абстракция, это реальность с Java 21.

🔧 Пример 1: 100 000 задач — без проблем
import java.util.concurrent.*;

public class Demo {
public static void main(String[] args) {
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
for (int i = 0; i < 100_000; i++) {
executor.submit(() -> {
Thread.sleep(1000);
return null;
});
}
}
}
}

⏱️ В обычных потоках такой код бы уронил JVM или занял бы гигабайты памяти.
А здесь — запускается моментально.

🔧 Пример 2: простой виртуальный поток без Executor'а
Thread.startVirtualThread(() -> {
System.out.println("Привет из виртуального потока!");
});

Никаких ExecutorService, никаких пулов — просто и понятно.

🔧 Пример 3: параллельные HTTP-запросы
var urls = List.of(
"https://example.com", "https://google.com", "https://github.com"
);

try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
urls.forEach(url -> executor.submit(() -> {
var content = new String(new URL(url).openStream().readAllBytes());
System.out.println("Получено с " + url + ": " + content.length() + " байт");
}));
}

📎 Virtual threads идеально подходят для сетевого I/O.

🔧 Пример 4: обработка запросов к серверу
while (true) {
var socket = serverSocket.accept();
Thread.startVirtualThread(() -> handle(socket));
}

Каждое подключение — отдельный виртуальный поток.
Такой сервер обрабатывает десятки тысяч клиентов — легко.


🗣️ Запомни: Ты больше не пишешь async-коллбеки и не страдаешь с пулом.
Теперь можно писать простой, читаемый blocking-код,
а JVM делает всю тяжёлую работу под капотом.
Please open Telegram to view this post
VIEW IN TELEGRAM
14👍5🔥2
☕️ `var` в Java — типы без шума

Java 10 принес var — возможность писать меньше кода без потери типов. Он не делает Java динамической, но помогает писать чище и быстрее.

⚡️ До и после var

📌 Было:
HashMap<String, List<Integer>> map = new HashMap<String, List<Integer>>();


📌 Стало:
var map = new HashMap<String, List<Integer>>();

👉 Код стал вдвое короче, но компилятор по-прежнему знает точный тип.


🔁 Циклы:
var list = List.of("A", "B", "C");

for (var item : list) {
System.out.println(item);
}

🔍 item — автоматически String. Работает идеально с Map:
var map = Map.of("one", 1, "two", 2);

for (var entry : map.entrySet()) {
System.out.println(entry.getKey() + " = " + entry.getValue());
}


🔄 Stream API
var names = List.of("john", "jane", "max");

var upper = names.stream()
.map((var name) -> name.toUpperCase())
.filter(n -> n.startsWith("J"))
.toList();

👉 Лаконично, читаемо, с сохранением типовой строгости.

🧪 Использование с методами
var user = getUser(); // Что возвращает getUser?


⚠️ Неочевидно. Лучше явно:
User user = getUser();

или хотя бы:
var user = getUser(); // getUser() → User

✍️ Пиши комментарий, если тип важен для читаемости.

💡 Когда var🔥

Тип очевиден из правой части:

  var url = new URL("https://example.com");


Тип слишком громоздкий:
  var map = new HashMap<String, Map<Integer, Set<List<String>>>>();


В локальных временных переменных:

  var tmp = Files.readAllLines(Path.of("file.txt"));


Когда лучше не использовать
var result = doStuff();

⚠️ Тип неочевиден — хуже читается. Особенно в API, сигнатурах и публичных методах:
// Так нельзя
public var getUser() { ... }


📛 var работает только локально, и только с инициализацией:
var x;           //  ошибка
var list = null; // ошибка



🗣️ Запомни: var — не фишка ради фишки. Он помогает избавиться от шума там, где типы очевидны. Не злоупотребляй, но используй — особенно в стримах, циклах, дженериках и временных переменных.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10🔥64👎4
В Java цикл for-each позволяет перебирать элементы массивов, коллекций и других итерируемых объектов без необходимости использовать индексы или итераторы. Однако, для того чтобы вы могли использовать for-each для перебора элементов своего собственного класса, этот класс должен реализовать интерфейс Iterable и предоставить метод iterator(), возвращающий объект, реализующий интерфейс Iterator.

В результате можно использовать for-each для перебора элементов этого класса, как если бы это был обычный массив или коллекция.

Вы можете адаптировать этот пример для своих собственных классов, реализуя интерфейс Iterable и предоставив соответствующий итератор, чтобы использовать for-each для вашего класса.
👍53👨‍💻2
⌨️ Полезные стримы. Группировка

Дан список людей с именем и городом проживания. Нужно сгруппировать их по городам.

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

record Person(String name, String city) {}

public class StreamExample {
public static void main(String[] args) {
List<Person> people = List.of(
new Person("Alice", "New York"),
new Person("Bob", "Los Angeles"),
new Person("Charlie", "New York"),
new Person("David", "Los Angeles"),
new Person("Edward", "San Francisco")
);

Map<String, List<Person>> peopleByCity = people.stream()
.collect(Collectors.groupingBy(Person::city));

peopleByCity.forEach((city, peopleInCity) -> {
System.out.println(city + ": " + peopleInCity.stream()
.map(Person::name)
.collect(Collectors.joining(", ")));
});
// Вывод:
// San Francisco: Edward
// New York: Alice, Charlie
// Los Angeles: Bob, David
}
}


#java #stream #grouping
Please open Telegram to view this post
VIEW IN TELEGRAM
1👍14🔥43
☕️ Эффектом observability: мониторинг Java‑микросервисов без бюджета

В микросервисной архитектуре наблюдаемость — не роскошь, а умение выжить в проде. Как сделать качественный мониторинг без затратных решений? Ответ в новой статье от Anderson Kuntz Meurer.

🔍 В статье вы узнаете:

📌 Три ключевых слоя наблюдаемости: метрики (Prometheus+Grafana), логи (Loki/ELK) и трассировки.
📌 Реальный пример: Docker‑стек с Spring Boot и Open Telemetry агентом.
📌 Как привязать @RestController к метрикам — HTTP‑статы, latency, ошибки.
📌 Как настроить сбор и визуализацию трассировки (spans, trace‑ID) между микро сервисами .
📌 Почему это — тот минимум, без которого продакшн‑микросервисы — не Продакшн.

➡️ Читайте и наслаждайтесь

🗣️ Бюджетный стек — не значит посредственный. Если хочешь стабильный, масштабируемый прод, начни с observability, сделай стек понятным и системным.

🤩 Java Фишки и трюки || #Java #Observability #Статья
Please open Telegram to view this post
VIEW IN TELEGRAM
2
🛰 Embedded JavaScript в JVM — запускаем JS в Java без WebView

Хочешь встроить JavaScript в Java-приложение?
Без браузера, без WebView, просто для вычислений, шаблонов, скриптов или конфигов?

Это возможно — через встроенные скриптовые движки. Работает с JDK 8+, на проде, без зависимостей (или с GraalVM).

Как это вообще работает?

Java включает JS-движок (Nashorn до Java 14), а после — можно подключить GraalVM JavaScript.

Через javax.script.ScriptEngine ты можешь:
🟢 выполнять JS-код;
🟢 вызывать JS-функции из Java;
🟢 передавать переменные между языками;
🟢 использовать JS как DSL внутри проекта.

🔧 Простой запуск скрипта
import javax.script.*;

public class Demo {
public static void main(String[] args) throws Exception {
ScriptEngine engine = new ScriptEngineManager().getEngineByName("javascript");
engine.eval("print('Привет из JavaScript');");
}
}

✔️ Всё — ты только что исполнил JS прямо в JVM.

📥 Передаём переменные
engine.put("name", "Neo");
engine.eval("print('Hello, ' + name);"); // Hello, Neo

Ты можешь прокидывать данные из Java в JS — и наоборот.

📌 Вызываем JS-функцию из Java
engine.eval("function add(a, b) { return a + b; }");

Invocable inv = (Invocable) engine;
Object result = inv.invokeFunction("add", 5, 7);

System.out.println(result); // 12

➡️ Используй как простую встроенную логику.

🧠 Пример — вычисление формулы из строки
String expr = "price * qty + tax";
Bindings vars = engine.createBindings();
vars.put("price", 100);
vars.put("qty", 2);
vars.put("tax", 50);

Object result = engine.eval(expr, vars);
System.out.println(result); // 250

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

⚙️ Подключение GraalVM JS (если JDK >14)
<dependency>
<groupId>org.graalvm.js</groupId>
<artifactId>js</artifactId>
<version>23.1.1</version>
</dependency>

Context context = Context.create("js");
Value result = context.eval("js", "2 + 2");
System.out.println(result.asInt()); // 4

GraalVM даёт современный JS с поддержкой всего ES6+.


🗣️ Запомни:Embedded JavaScript — это про гибкость без внешних зависимостей.
Хочешь дать пользователю конфиги на JS? Или динамически описывать поведение? Или быстро собрать вычислитель формул?Ты можешь запускать JavaScript напрямую в JVM — просто, безопасно и эффективно.
Please open Telegram to view this post
VIEW IN TELEGRAM
8🔥4🗿1
Посты на какие темы вы хотели бы увидеть на нашем канале? Пишите в комметариях.
10
⛓️ Chain of Responsibility на enum-ах — антипаттерн, который работает

Chain of Responsibility — это когда у тебя есть цепочка проверок или действий, которые обрабатываются по очереди, пока не будет «готово» или «отказ».
В Java обычно это: интерфейс + куча обработчиков.
Но можно сделать проще: на `enum` с абстрактными методами.

🔧 Пример: валидация пользователя
enum UserValidator {
CHECK_NAME {
boolean validate(User u) {
return u.name != null && !u.name.trim().isEmpty();
}
},
CHECK_AGE {
boolean validate(User u) {
return u.age >= 18;
}
},
CHECK_EMAIL {
boolean validate(User u) {
return u.email != null && u.email.contains("@");
}
};

abstract boolean validate(User u);
}

Каждый enum — это как мини-обработчик.
Ты прямо внутри перечисления задаёшь поведение.
Код не размазан по 10 классам и не требует интерфейсов.

🔁 Проверка по цепочке
User user = new User("Neo", 30, "neo@matrix.io");

boolean valid = Arrays.stream(UserValidator.values())
.allMatch(v -> v.validate(user));

➡️ Если все валидаторы вернули true — пользователь валиден.

⚠️ Обработка ошибок поимённо
Arrays.stream(UserValidator.values())
.filter(v -> !v.validate(user))
.forEach(v -> System.out.println("⛔️ Ошибка в: " + v.name()));

📌Ты можешь узнать, что именно не прошло, без лишних if'ов.

🧪 Альтернатива: остановиться на первом ошибочном
Optional<UserValidator> failed = Arrays.stream(UserValidator.values())
.filter(v -> !v.validate(user))
.findFirst();

if (failed.isPresent()) {
System.out.println("Провал на шаге: " + failed.get().name());
}

➡️ Удобно, если хочешь быстро выйти из цепочки.

📦 Всё это работает с обычными классами
class User {
String name;
int age;
String email;

User(String name, int age, String email) {
this.name = name;
this.age = age;
this.email = email;
}
}


🗣️ Запомни: Иногда enum с методами — это рабочий компромисс, когда не хочется поднимать тяжёлый Chain of Responsibility.Просто, читаемо, удобно. Особенно для валидаций, фильтров, конвертаций и тестов.
Please open Telegram to view this post
VIEW IN TELEGRAM
117🤔5❤‍🔥1👨‍💻1
Media is too big
VIEW IN TELEGRAM
☕️Введение в Swing | Как создать графический калькулятор на Java?

Это видео показывает, как создать простой графический калькулятор на Java с использованием Swing. Подойдёт новичкам: шаг за шагом разбирается создание кнопок, полей ввода и обработка событий. Отличный старт для изучения GUI-разработки на Java.


🤩 Java Фишки и трюки || #Видео
Please open Telegram to view this post
VIEW IN TELEGRAM
👍32
👻 Ghost Interfaces: тип как флаг без логики — и это работает

Java позволяет создавать интерфейсы без методов. Они ничего не делают.
Но если ты дашь этот интерфейс классу — ты отмечаешь объект как "особенный".
Это и есть ghost interface — маркерный интерфейс, флаг через тип.

📛 Пример: метка для доступа
public interface AdminAccess {
// ничего не требует, просто существует
}


public class User {}

public class AdminUser extends User implements AdminAccess {}

➡️ AdminUser не обязан ничего переопределять.
Но теперь ты можешь понять, что это админ, просто глядя на тип.

🧪 Проверка — через instanceof
void check(User u) {
if (u instanceof AdminAccess) {
System.out.println(" Доступ разрешён");
} else {
System.out.println("⛔️ Нет прав");
}
}

➡️ Вот где начинается магия: поведение зависит от типа, а не от полей или флагов.

🛠 Применение на практике

Смотри, тебе нужно различать обычные запросы и те, что требуют валидации.
Не хочешь городить if (request.needsValidation())? — решается в один тип.
public interface RequiresValidation {}

public class LoginRequest implements RequiresValidation {}
public class PingRequest {}


void handle(Object req) {
if (req instanceof RequiresValidation) {
System.out.println("🔍 Проверка данных");
} else {
System.out.println("🚀 Без валидации");
}
}

➡️ Никаких полей. Просто интерфейс как ярлык.

💾 Другой кейс — запрет на сохранение
public interface ReadOnly {}

public class ConfigFile implements ReadOnly {}
public class LogFile {}


void save(Object file) {
if (file instanceof ReadOnly) {
throw new RuntimeException(" Это read-only");
}
System.out.println("💾 Сохраняем файл...");
}

➡️ Без boolean readonly, без .getPermissions()просто instanceof.

📦 Комбинации: объект — это набор флагов
public interface JsonSerializable {}
public interface RequiresAuth {}

public class ApiRequest implements JsonSerializable, RequiresAuth {}


if (req instanceof JsonSerializable) {
System.out.println("📤 Преобразуем в JSON");
}
if (req instanceof RequiresAuth) {
System.out.println("🔐 Проверяем токен");
}

➡️ Всё как в декларации типа: сам объект описывает себя.

📚 enum тоже работает
public interface Internal {}

public enum Command implements Internal {
REBOOT, SHUTDOWN
}

void dispatch(Enum<?> cmd) {
if (cmd instanceof Internal) {
System.out.println("🔐 Внутренняя команда");
} else {
System.out.println("🌍 Публичная");
}
}

➡️ Даже enum может быть "помечен" ghost-интерфейсом.


🗣 Запомни: Ghost Interfaces — это не костыль, а чистый, типовой способ описывать поведение.Они не делают, а говорят. Всё, что нужно — instanceof.Пиши логику по типу, не по данным.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥10👍63👨‍💻3
🧪 Java Agents — как влезть в чужой .jar и следить за ним изнутри

Нужно посмотреть, какие классы грузятся в рантайме?
Или вставить лог прямо в чужой метод, не трогая исходник?

Java Agent запускается до `main()` и даёт доступ ко всему, что загружается в JVM.

🔧 Шаг 🔢: создаём агент
public class SpyAgent {
public static void premain(String args, Instrumentation inst) {
System.out.println("👁 Агент стартовал");
}
}

➡️ Метод premain() будет вызван раньше `main()` обычного приложения.
Параметры:

🟢 args — аргументы, переданные агенту
🟢 Instrumentation — интерфейс для перехвата и изменения классов

🧲 Шаг 🔢: перехватываем загрузку классов
inst.addTransformer(new ClassFileTransformer() {
@Override
public byte[] transform(ClassLoader loader, String className,
Class<?> classBeingRedefined, ProtectionDomain domain,
byte[] classfileBuffer) {
if (className.contains("Service")) {
System.out.println("🎯 Загружается: " + className);
}
return null;
}
});

➡️ Каждый раз, когда JVM грузит класс — агент получает байты.
Если хочешь, можешь их изменить и отдать «новую» версию класса.

🗂 Шаг🔢: манифест — как JVM узнает, что это агент

Создаём MANIFEST.MF:
Premain-Class: SpyAgent
Can-Redefine-Classes: true


Собираем .jar с этим манифестом:
jar cmf MANIFEST.MF spy-agent.jar SpyAgent.class


🚀 Шаг 4: подключаем агент к приложению
java -javaagent:spy-agent.jar -jar victim.jar

➡️ JVM загрузит твой агент, вызовет premain(), и только потом запустит main() из victim.jar.

🔁 Пример: вставляем поведение с ByteBuddy
new AgentBuilder.Default()
.type(named("com.example.Target"))
.transform((builder, type, cl, module) ->
builder.method(named("process"))
.intercept(MethodDelegation.to(LoggerInterceptor.class))
).installOn(inst);


public class LoggerInterceptor {
@RuntimeType
public static void intercept() {
System.out.println("📦 Метод process() вызван");
}
}

➡️ Агент находит нужный класс, перехватывает метод и вставляет лог.
Ты не меняешь исходник — всё происходит на лету, при загрузке.

🧱 Структура проекта:
spy-agent/
├── SpyAgent.java
├── LoggerInterceptor.java
├── MANIFEST.MF


🗣️ Запомни: Java Agent — это способ влезть в чужое приложение до его запуска.Ты можешь видеть всё, что грузится, менять методы, добавлять поведение — не касаясь исходников и не пересобирая .jar.
Please open Telegram to view this post
VIEW IN TELEGRAM
8👍6👨‍💻5