uk
Feedback
Java | Фишки и трюки

Java | Фишки и трюки

Відкрити в Telegram

Java: примеры кода, интересные фишки и полезные трюки Купить рекламу: https://telega.in/c/java_tips_and_tricks ✍️По всем вопросам: @Pascal4eg Менеджер по рекламе: @shmyzna

Показати більше
6 953
Підписники
-324 години
-27 днів
+630 день
Архів дописів
⚙️ Java Core — что реально важно понимать Java Core — это не просто "синтаксис", это то, на чём держится весь язык: классы, объекты, память, потоки, исключения. Ни Spring, ни фреймворки не помогут, если ты не знаешь базу. 📦 Классы и объекты
class User {
    String name;
    int age;

    void sayHello() {
        System.out.println("Привет, меня зовут " + name);
    }
}

User u = new User();
u.name = "Иван";
u.sayHello();
➡️ Всё в Java — объект. Класс — это чертёж. Объект — это реальность. 👷 Конструкторы и перегрузка
class Point {
    int x, y;

    Point() {
        this(0, 0);
    }

    Point(int x, int y) {
        this.x = x;
        this.y = y;
    }
}
➡️ this(...) вызывает другой конструктор — удобно задавать значения по умолчанию. 🧱 Наследование и super
class 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("Печать книги");
    }
}
➡️ Интерфейс задаёт что умеет объект, но не как именно. 🔁 Память: stack vs heap
void run() {
    int x = 10;              // stack
    String name = "Java";    // heap (объект)
}
➡️ Локальные переменные — в стеке. Объекты и массивы — в куче (heap). 🪓 Final, static, this
class Example {
    static int count = 0;
    final int id;

    Example() {
        this.id = ++count;
    }
}
🟢 final — нельзя переопределить/изменить 🟢 static — общая переменная на все объекты 🟢 this — текущий объект 🔄 Циклы, итераторы, foreach
List<String> names = List.of("Alice", "Bob");

for (String name : names) {
    System.out.println(name);
}
➡️ Работает с коллекциями, массивами, любым, что реализует Iterable. 🧰 try-catch-finally
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
🟢 == сравнивает ссылки 🟢 .equals() сравнивает содержимое 🧵 Потоки (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 — пары ключ-значение 📚 Generic'и
class Box<T> {
    T value;

    void set(T value) { this.value = value; }
    T get() { return value; }
}
➡️ Box<String>, Box<Integer>типизируешь класс под себя. 🗣️ Запомни: Java Core — это то, что ты используешь каждый день, даже если не замечаешь. Понимание классов, памяти, коллекций, исключений и потоков — это не “для экзамена”, это основа всей архитектуры твоего кода.

⚙️ "Bytecode Engineering" с ASM и Byte Buddy: правим классы на лету Хочешь подменить метод в чужом классе, не трогая исходники? Или генерировать новый класс динамически? В 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. 🧠 Byte Buddy: высокоуровневая альтернатива
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. 🗣️ Запомни:Bytecode-инжиниринг даёт тебе контроль над классами после компиляции. ASM — это scalpel. Byte Buddy — это лего. Если нужно вставить поведение в рантайме — это твой инструмент.

❗ТОП 2 канала для тех, кто хочет хочет развиваться в кибербезе 🔤Project Omega — закрытая лаборатория белого хакера. Криптогр
ТОП 2 канала для тех, кто хочет хочет развиваться в кибербезе 🔤Project Omega закрытая лаборатория белого хакера. Криптография на практике и разборы популярных инструментов защиты. 🔤no system is safe // cybersec — один из древнейших ресурсов по информационной безопасности в рунете. Книги, курсы, полезные тулсы, уроки по Linux, новости клирнета.

🧪 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.

Как живет айтишник, который зарабатывает 5000$ в мес? Живет хорошо! За глубокие знания и умение решать самые сложные задачи его ценят в любой команде: от стартапа до крупной корпорации. А он умеет продавать себя, получать лучшие предложения на работу и эффективно распределять время. Для этого нужно всего 5 минут в день читать канал айтишника. Здесь вы найдёте практические советы, инсайды и секреты от разработчика с 11+ лет опыта, о которых не рассказывают на курсах. 5 минут на канале заменят месяцы самостоятельного изучения. Подписывайтесь: https://t.me/+WCs9hbWsww1iZjJi

👻 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.Пиши логику по типу, не по данным.

⚡️Хотите стать Android-разработчиком и создавать масштабируемые мобильные приложения с нуля? Курс «Android Developer» идеален
⚡️Хотите стать Android-разработчиком и создавать масштабируемые мобильные приложения с нуля? Курс «Android Developer» идеален для новичков, которые хотят попасть в IT, а также для тестировщиков и сисадминов, желающих перейти в разработку. За 10 месяцев обучения вы освоите Kotlin, научитесь разрабатывать приложения на Android SDK, работать с фреймворками Dagger2, RxJava и Jetpack Compose, а также освоите тестирование и CI/CD. Мы научим вас проектировать многомодульные архитектуры, работать с базами данных (Room, DataStore), создавать UI, использовать современные фреймворки и оптимизировать приложения. Все это с реальными задачами, которые помогут вам построить сильное портфолио и стать успешным разработчиком. 📲Оставьте заявку и получите скидку на обучение: https://otus.pw/qWbB/ Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576

☕️Введение в Swing | Как создать графический калькулятор на Java?
Это видео показывает, как создать простой графический калькулятор на Java с использованием Swing. Подойдёт новичкам: шаг за шагом разбирается создание кнопок, полей ввода и обработка событий. Отличный старт для изучения GUI-разработки на Java.
🤩 Java Фишки и трюки || #Видео

⛓️ 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.Просто, читаемо, удобно. Особенно для валидаций, фильтров, конвертаций и тестов.

Посты на какие темы вы хотели бы увидеть на нашем канале? Пишите в комметариях.

🛰 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 — просто, безопасно и эффективно.

😈Переиграли и уничтожили SkillBox’y привет, всем остальным соболезную. Залили новые курсы, забирайте ниже: ➖Python (64гб кур
😈Переиграли и уничтожили SkillBox’y привет, всем остальным соболезную. Залили новые курсы, забирайте ниже: Python (64гб курсов) ➖C# (27гб курсов) ➖Java (45гб курсов) ➖PHP (34гб курсов) ➖Go (23гб курсов) ➖Rust (37гб курсов) ➖SQL (41гб курсов) ➖MySQL (21гб курсов) ➖Другое (114гб курсов) Не видео на ютуб, а реальный СЛИВ огромных баз. Проверь сам!🚨

☕️ Эффектом observability: мониторинг Java‑микросервисов без бюджета В микросервисной архитектуре наблюдаемость — не роскошь,
☕️ Эффектом observability: мониторинг Java‑микросервисов без бюджета В микросервисной архитектуре наблюдаемость — не роскошь, а умение выжить в проде. Как сделать качественный мониторинг без затратных решений? Ответ в новой статье от Anderson Kuntz Meurer. 🔍 В статье вы узнаете: 📌 Три ключевых слоя наблюдаемости: метрики (Prometheus+Grafana), логи (Loki/ELK) и трассировки. 📌 Реальный пример: Docker‑стек с Spring Boot и Open Telemetry агентом. 📌 Как привязать @RestController к метрикам — HTTP‑статы, latency, ошибки. 📌 Как настроить сбор и визуализацию трассировки (spans, trace‑ID) между микро сервисами . 📌 Почему это — тот минимум, без которого продакшн‑микросервисы — не Продакшн. ➡️ Читайте и наслаждайтесь 🗣️ Бюджетный стек — не значит посредственный. Если хочешь стабильный, масштабируемый прод, начни с observability, сделай стек понятным и системным. 🤩 Java Фишки и трюки || #Java #Observability #Статья

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

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

🖥 Хочешь прокачаться в Java, но устал от разбросанных туториалов? Ты теряешь месяцы на YouTube, когда всё можно было бы умес
+6
🖥 Хочешь прокачаться в Java, но устал от разбросанных туториалов? Ты теряешь месяцы на YouTube, когда всё можно было бы уместить в один PDF 📄 Авторы крупнейшего Java канал сделали PDF-гайд, в котором всё по-человечески: • без воды • с примерами • коротко и по делу Отлично подходит для новичков Понял → Применил → Пошёл дальше Получить полностью бесплатный гайд можно здесь.

В Java цикл for-each позволяет перебирать элементы массивов, коллекций и других итерируемых объектов без необходимости исполь
В Java цикл for-each позволяет перебирать элементы массивов, коллекций и других итерируемых объектов без необходимости использовать индексы или итераторы. Однако, для того чтобы вы могли использовать for-each для перебора элементов своего собственного класса, этот класс должен реализовать интерфейс Iterable и предоставить метод iterator(), возвращающий объект, реализующий интерфейс Iterator. В результате можно использовать for-each для перебора элементов этого класса, как если бы это был обычный массив или коллекция. Вы можете адаптировать этот пример для своих собственных классов, реализуя интерфейс Iterable и предоставив соответствующий итератор, чтобы использовать for-each для вашего класса.

⭐⭐🖥🖥🧑‍💻👩‍💻🖥⭐⭐📢 Казань, пора выкатывать лето на прод 12 июля в вашем городе пройдет ИТ-фестиваль «Сезон кода» для опыт
⭐⭐🖥🖥🧑‍💻👩‍💻🖥⭐⭐📢 Казань, пора выкатывать лето на прод 12 июля в вашем городе пройдет ИТ-фестиваль «Сезон кода» для опытных backend-разработчиков, аналитиков, QA-инженеров и других специалистов. Группа Т-Технологий и спикеры из Т-Банка зовут обмениваться опытом и слушать доклады под открытым небом. Будет 3 секции, где вы узнаете: — Как клиентоориентированный код решает задачи пользователей и бизнеса. — Как идеи становятся технологиями и упрощают работу инженеров. — Какие приемы используются в backend-разработке и как устроены продукты группы Т-Технологий. Кейсы, вдохновение и развлечения тоже будут. Успейте зарегистрироваться до 10 июля. Подробности тут

☕️ `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 — не фишка ради фишки. Он помогает избавиться от шума там, где типы очевидны. Не злоупотребляй, но используй — особенно в стримах, циклах, дженериках и временных переменных.

🧵 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 делает всю тяжёлую работу под капотом.