List.of() в Java — быстро, но не всегда безопасноС Java 9 появился удобный способ создать список:
List<String> names = List.of("Alice", "Bob", "Charlie");Выглядит лаконично, работает быстро — но есть нюанс.
List<String> list = List.of("a", "b");
list.add("c"); // 💥 UnsupportedOperationException
list.remove("a"); // 💥 тоже ошибкаЛюбая попытка изменить список — ошибка во время выполнения. Это не
ArrayList, а immutable List.List<String> list = List.of("hello", null); // 💥 NullPointerExceptionДаже один
null — и всё падает. Потому что List.of() не допускает null ни в одном элементе.System.out.println(List.of("a", "b").getClass());
// class java.util.ImmutableCollections$ListNЭто не
ArrayList, не LinkedList. Это внутренний тип, оптимизированный под неизменяемость.Если твой код ждёт
ArrayList и будет кастить — ловишь ClassCastException.List.of(DAYS))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
🔥13❤5
🧵 Используй try-with-resources с потоками правильно (и продвинуто)
Если ты до сих пор закрываешь потоки руками или думаешь, что try-with-resources — это только для файлов, смотри:
🛠 Пример 1: чтение и закрытие автоматически
☑️ Поток закрывается автоматически — даже если внутри случится исключение.
🧪 Пример 2: кастомный ресурс (любой AutoCloseable)
🧠 Всё, что реализует AutoCloseable, можно оборачивать в try-with-resources. Это не только файлы, но и сетевые соединения, стримы, логи, сессии Hibernate и др.
🕸 Пример 3: несколько ресурсов
🔒 Все ресурсы закроются в обратном порядке.
🗣️ Запомни: try-with-resources — не просто синтаксический сахар. Это способ писать надёжный код без утечек ресурсов и без лишнего шаблонного кода. Особенно полезно при работе с сетью, файлами, базами данных и внешними API.
Если ты до сих пор закрываешь потоки руками или думаешь, что try-with-resources — это только для файлов, смотри:
try (BufferedReader reader = Files.newBufferedReader(Path.of("data.txt"))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
}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();
}try (
InputStream in = new FileInputStream("input.txt");
OutputStream out = new FileOutputStream("output.txt")
) {
in.transferTo(out);
}
Please open Telegram to view this post
VIEW IN TELEGRAM
❤8👍6🔥4
Считаешь Java не для AI? Серьёзно ошибаешься! LangChain, фреймворк для разработки с языковыми моделями, теперь уже доступен и для Java — через LangChain4J.
В статье ты узнаешь:
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4❤2🔥2👏1
🌀 Pattern Matching в Java — прощай `instanceof + cast`
Раньше, чтобы проверить тип и привести его, писали вот так:
👎 Шумно, опасно, повторяется.
С Java 16+ можно проще и безопаснее — паттерн-матчинг для `instanceof`:
✔️ Как это работает:
✅ Если
Больше никаких ручных кастов.
🛠 Примеры на практике:
☑️ Проверка нескольких типов
🔍 Код стал чище: без каста, без дублирования
🚀 Использование внутри
С Java 21 (preview) можно использовать
➡️ Это называется Pattern Matching for switch.
🧩 Совмещение с guard'ами
⚠️
🧪 Более сложные условия
Можно комбинировать с
🗣️ Запомни: Используй
Раньше, чтобы проверить тип и привести его, писали вот так:
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());
}obj — String, то переменная 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 -> "Неизвестно";
};
}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
👍13❤3🔥2👨💻1
Stream API — мощный инструмент, но легко попасть в ловушку, если не знать нюансов.
List<String> names = users.stream()
.filter(u -> u.isActive())
.map(User::getName)
.collect(Collectors.toList());
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()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());
Всегда помни про однократность, лень и null — и всё будет летать.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍15❤6🔥2❤🔥1
Используешь Stream в Java 8+? Только не думай, что это всегда просто и быстро. В этой статье — реальные кейсы и трюки, которые позволят ускорить обработку коллекций и избежать типичных ошибок.
В статье ты узнаешь:
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3❤1
Хочешь писать Java-код, который приятно читать и легко сопровождать?
Вот не теория с книжек, а настоящие идиомы, шаблоны и фишки, которые делают код чистым, понятным и «живым».
double d = get(a, b);
double distance = calculateDistance(startPoint, endPoint);
Именуй переменные и методы так, чтобы код сам говорил, что он делает.
if (isAdmin) {
grantAccess();
} else {
denyAccess();
}if (!isAdmin) {
denyAccess();
return;
}
grantAccess();Меньше вложенности → легче читать.
public void start(boolean silent) {
if (!silent) {
System.out.println("Starting...");
}
// ...
}public void startLoud() {
System.out.println("Starting...");
start();
}
public void start() {
// ...
}Выноси поведение в отдельные методы, а не в булевы флаги.
String name = user.getName();
Optional<String> name = user.getNameOptional();
name.ifPresent(System.out::println);
Optional показывает, что значение может отсутствовать.
send(2);
send(Priority.HIGH);
enum передаёт смысл.
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.
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();
};Чётко, лаконично, без лишнего кода.
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) { ... }Каждый метод делает одну вещь. Легко тестировать, легко читать.
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());
Чисто, выразительно, без шума.
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 задач — без проблем
⏱️ В обычных потоках такой код бы уронил JVM или занял бы гигабайты памяти.
А здесь — запускается моментально.
🔧 Пример 2: простой виртуальный поток без Executor'а
Никаких ExecutorService, никаких пулов — просто и понятно.
🔧 Пример 3: параллельные HTTP-запросы
📎 Virtual threads идеально подходят для сетевого I/O.
🔧 Пример 4: обработка запросов к серверу
Каждое подключение — отдельный виртуальный поток.
Такой сервер обрабатывает десятки тысяч клиентов — легко.
🗣️ Запомни: Ты больше не пишешь async-коллбеки и не страдаешь с пулом.
Теперь можно писать простой, читаемый blocking-код,
а JVM делает всю тяжёлую работу под капотом.
Хочешь запускать 10 000 параллельных задач в Java без боли с thread pool?
Теперь можно — с virtual threads. Это не абстракция, это реальность с Java 21.
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;
});
}
}
}
}
А здесь — запускается моментально.
Thread.startVirtualThread(() -> {
System.out.println("Привет из виртуального потока!");
});Никаких ExecutorService, никаких пулов — просто и понятно.
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() + " байт");
}));
}
while (true) {
var socket = serverSocket.accept();
Thread.startVirtualThread(() -> handle(socket));
}Каждое подключение — отдельный виртуальный поток.
Такой сервер обрабатывает десятки тысяч клиентов — легко.
Теперь можно писать простой, читаемый blocking-код,
а JVM делает всю тяжёлую работу под капотом.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤14👍5🔥2
Java 10 принес
var — возможность писать меньше кода без потери типов. Он не делает Java динамической, но помогает писать чище и быстрее.varHashMap<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());
}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();
// Так нельзя
public var getUser() { ... }
📛
var работает только локально, и только с инициализацией:var x; // ❌ ошибка
var list = null; // ❌ ошибка
var — не фишка ради фишки. Он помогает избавиться от шума там, где типы очевидны. Не злоупотребляй, но используй — особенно в стримах, циклах, дженериках и временных переменных.Please open Telegram to view this post
VIEW IN TELEGRAM
👍10🔥6❤4👎4
В Java цикл for-each позволяет перебирать элементы массивов, коллекций и других итерируемых объектов без необходимости использовать индексы или итераторы. Однако, для того чтобы вы могли использовать for-each для перебора элементов своего собственного класса, этот класс должен реализовать интерфейс
В результате можно использовать for-each для перебора элементов этого класса, как если бы это был обычный массив или коллекция.
Вы можете адаптировать этот пример для своих собственных классов, реализуя интерфейс
Iterable и предоставить метод iterator(), возвращающий объект, реализующий интерфейс Iterator.В результате можно использовать for-each для перебора элементов этого класса, как если бы это был обычный массив или коллекция.
Вы можете адаптировать этот пример для своих собственных классов, реализуя интерфейс
Iterable и предоставив соответствующий итератор, чтобы использовать for-each для вашего класса.👍5❤3👨💻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🔥4❤3
В микросервисной архитектуре наблюдаемость — не роскошь, а умение выжить в проде. Как сделать качественный мониторинг без затратных решений? Ответ в новой статье от Anderson Kuntz Meurer.
@RestController к метрикам — HTTP‑статы, latency, ошибки.Please open Telegram to view this post
VIEW IN TELEGRAM
❤2
Хочешь встроить JavaScript в Java-приложение?
Без браузера, без WebView, просто для вычислений, шаблонов, скриптов или конфигов?
Это возможно — через встроенные скриптовые движки. Работает с JDK 8+, на проде, без зависимостей (или с GraalVM).
Java включает JS-движок (Nashorn до Java 14), а после — можно подключить GraalVM JavaScript.
Через
javax.script.ScriptEngine ты можешь:import javax.script.*;
public class Demo {
public static void main(String[] args) throws Exception {
ScriptEngine engine = new ScriptEngineManager().getEngineByName("javascript");
engine.eval("print('Привет из JavaScript');");
}
}
engine.put("name", "Neo");
engine.eval("print('Hello, ' + name);"); // Hello, NeoТы можешь прокидывать данные из Java в JS — и наоборот.
engine.eval("function add(a, b) { return a + b; }");
Invocable inv = (Invocable) engine;
Object result = inv.invokeFunction("add", 5, 7);
System.out.println(result); // 12String 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
Очень удобно для настройки расчётов пользователем без пересборки кода.
<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()); // 4GraalVM даёт современный JS с поддержкой всего ES6+.
Хочешь дать пользователю конфиги на JS? Или динамически описывать поведение? Или быстро собрать вычислитель формул?Ты можешь запускать JavaScript напрямую в JVM — просто, безопасно и эффективно.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤8🔥4🗿1
Посты на какие темы вы хотели бы увидеть на нашем канале? Пишите в комметариях.
❤10
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()));
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
1❤17🤔5❤🔥1👨💻1
Media is too big
VIEW IN TELEGRAM
Это видео показывает, как создать простой графический калькулятор на Java с использованием Swing. Подойдёт новичкам: шаг за шагом разбирается создание кнопок, полей ввода и обработка событий. Отличный старт для изучения GUI-разработки на Java.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3❤2
Java позволяет создавать интерфейсы без методов. Они ничего не делают.
Но если ты дашь этот интерфейс классу — ты отмечаешь объект как "особенный".
Это и есть ghost interface — маркерный интерфейс, флаг через тип.
📛 Пример: метка для доступа
public interface AdminAccess {
// ничего не требует, просто существует
}public class User {}
public class AdminUser extends User implements AdminAccess {}AdminUser не обязан ничего переопределять.Но теперь ты можешь понять, что это админ, просто глядя на тип.
instanceofvoid 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("🔐 Проверяем токен");
}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("🌍 Публичная");
}
}instanceof.Пиши логику по типу, не по данным.Please open Telegram to view this post
VIEW IN TELEGRAM
🔥10👍6❤3👨💻3
.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;
}
});Если хочешь, можешь их изменить и отдать «новую» версию класса.
Создаём
MANIFEST.MF:Premain-Class: SpyAgent
Can-Redefine-Classes: true
Собираем
.jar с этим манифестом:jar cmf MANIFEST.MF spy-agent.jar SpyAgent.class
java -javaagent:spy-agent.jar -jar victim.jar
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
.jar.Please open Telegram to view this post
VIEW IN TELEGRAM
❤8👍6👨💻5
Хочешь подменить метод в чужом классе, не трогая исходники? Или генерировать новый класс динамически? В Java это делается через байткод-инжиниринг — на уровне JVM-инструкций.
ASM: низкоуровневый контроль
public class AddPrintAdapter extends MethodVisitor {
public AddPrintAdapter(MethodVisitor mv) {
super(Opcodes.ASM9, mv);
}
@Override
public void visitCode() {
super.visitCode();
mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
mv.visitLdcInsn("🔥 Метод вызван");
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream",
"println", "(Ljava/lang/String;)V", false);
}
}System.out.println() в начало любого метода. Работа с visitCode() — прямой доступ к байткоду.ClassReader reader = new ClassReader("com.example.Foo");
ClassWriter writer = new ClassWriter(reader, 0);
ClassVisitor visitor = new ClassVisitor(Opcodes.ASM9, writer) {
@Override
public MethodVisitor visitMethod(int access, String name, String desc,
String signature, String[] exceptions) {
MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
if (name.equals("run")) {
return new AddPrintAdapter(mv);
}
return mv;
}
};
reader.accept(visitor, 0);
byte[] modifiedClass = writer.toByteArray();run, встроили println() — и получили новый .class.new ByteBuddy()
.subclass(Object.class)
.name("com.example.DynamicClass")
.defineMethod("hello", void.class, Modifier.PUBLIC)
.intercept(MethodDelegation.to(HelloInterceptor.class))
.make()
.load(ClassLoader.getSystemClassLoader());
hello() прямо во время выполнения. Без .java-файлов, всё в памяти.public class HelloInterceptor {
@RuntimeType
public static void intercept() {
System.out.println("👋 Hello from dynamic method");
}
}hello() будет выполнен этот перехватчик. Никаких аннотаций, никакой магии — только Java.Please open Telegram to view this post
VIEW IN TELEGRAM
👨💻8👍4
Java Core — это не просто "синтаксис", это то, на чём держится весь язык: классы, объекты, память, потоки, исключения. Ни Spring, ни фреймворки не помогут, если ты не знаешь базу.
class User {
String name;
int age;
void sayHello() {
System.out.println("Привет, меня зовут " + name);
}
}
User u = new User();
u.name = "Иван";
u.sayHello();class Point {
int x, y;
Point() {
this(0, 0);
}
Point(int x, int y) {
this.x = x;
this.y = y;
}
}this(...) вызывает другой конструктор — удобно задавать значения по умолчанию.superclass Animal {
void speak() {
System.out.println("звук");
}
}
class Dog extends Animal {
void speak() {
super.speak();
System.out.println("гав");
}
}super нужен, когда хочешь использовать поведение родителя, а не полностью переопределять.interface Printable {
void print();
}
class Book implements Printable {
public void print() {
System.out.println("Печать книги");
}
}void run() {
int x = 10; // stack
String name = "Java"; // heap (объект)
}🪓 Final, static, this
class Example {
static int count = 0;
final int id;
Example() {
this.id = ++count;
}
}final — нельзя переопределить/изменитьstatic — общая переменная на все объектыthis — текущий объектList<String> names = List.of("Alice", "Bob");
for (String name : names) {
System.out.println(name);
}Iterable.try {
int x = 1 / 0;
} catch (ArithmeticException e) {
System.out.println("Ошибка: деление на 0");
} finally {
System.out.println("Завершение");
}finally выполнится всегда. Можно использовать для закрытия ресурсов.⚡️ Вложенные классы и лямбды
Runnable r = () -> System.out.println("Привет из потока");
new Thread(r).start();equals() ==String a = "test";
String b = new String("test");
System.out.println(a == b); // false
System.out.println(a.equals(b)); // true
🧵 Потоки (Thread) и синхронизация
class Task extends Thread {
public void run() {
System.out.println("Поток: " + Thread.currentThread().getName());
}
}
new Task().start();start() запускает поток асинхронно. run() — просто метод, вызовется как обычный.List<String> list = new ArrayList<>();
Set<String> set = new HashSet<>();
Map<String, Integer> map = new HashMap<>();
List — упорядоченный списокSet — уникальные элементыMap — пары ключ-значениеclass Box<T> {
T value;
void set(T value) { this.value = value; }
T get() { return value; }
}Box<String>, Box<Integer> — типизируешь класс под себя.Java Core — это то, что ты используешь каждый день, даже если не замечаешь. Понимание классов, памяти, коллекций, исключений и потоков — это не “для экзамена”, это основа всей архитектуры твоего кода.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤17👍5🔥4❤🔥1👨💻1