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 и Безопасность: как защищают приложения в 2025 году

Безопасность давно перестала быть опцией — это must-have. В 2025 Java предлагает разработчику целый арсенал встроенных решений и новых подходов для защиты своих сервисов.

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

📌 Какие уязвимости до сих пор типичны для Java-приложений и как их избежать.
📌 Как работают современные security-фреймворки: Spring Security, OPA, Keycloak.
📌 Что такое Zero Trust архитектура и как реализовать её на Java.
📌 Почему OAuth 2.1, JWT и mTLS — это уже не “просто мода”, а стандарт де-факто.

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

🗣️ Вывод: в мире Java безопасность — это уже не боль, а гибкий и удобный инструментарий. Главное — начать использовать правильно.

🤩 Java Фишки и трюки || #Cтатья #JavaSecurity #SpringSecurity #ZeroTrust
Please open Telegram to view this post
VIEW IN TELEGRAM
👍32🔥2👨‍💻1
☕️ Hibernate: ORM без боли

Hibernate — это Object-Relational Mapping.
Он превращает твои Java-классы в таблицы и наоборот.
Без JDBC, без ручных SQL-запросов — читаешь и сохраняешь объекты как есть.

📦 Сущность = таблица
@Entity
@Table(name = "users")
public class User {

@Id
@GeneratedValue
private Long id;

private String name;

@Column(name = "email_address")
private String email;

// геттеры/сеттеры
}

🟢 @Entity превращает класс в таблицу
🟢 @Id — это первичный ключ
🟢 @Column — имя колонки, если отличается от поля

🔁 Чтение и запись без SQL
User u = new User();
u.setName("Alice");
u.setEmail("a@example.com");

session.save(u);

🟢 Hibernate сам делает INSERT INTO users ... под капотом.
🟢 Объекты = строки в таблице. Не нужно писать SQL — только работать с Java.

🔍 Поиск через HQL (Hibernate Query Language)
List<User> users = session
.createQuery("from User where email like :e", User.class)
.setParameter("e", "%@gmail.com")
.getResultList();

➡️ from User — это не SQL, а HQL. Работает на уровне классов, не таблиц.

🤝 Связи между таблицами
@Entity
public class Order {

@Id @GeneratedValue
private Long id;

@ManyToOne
private User user;

private String product;
}

➡️ Один User — много Order. Hibernate сам создаст user_id в таблице заказов.

User u = session.get(User.class, 1L);
List<Order> orders = u.getOrders(); // автоматический join

➡️ Хочешь lazy, eager — всё регулируется аннотациями.

📋 Обновление и удаление
User u = session.get(User.class, 2L);
u.setName("Bob");
session.update(u);


session.delete(u);

➡️ Hibernate сам решает, какие SQL-команды вызвать — ты просто работаешь с объектами.

🔄 Автоматическое создание таблиц
spring.jpa.hibernate.ddl-auto=update

➡️ Таблицы создаются автоматически по твоим сущностям.

🗣️ Запомни:
Hibernate — это способ писать код, а не SQL. Он мапит Java-объекты на реляционные таблицы, сам управляет транзакциями, связями, сессиями.
Но главное — он не магия, и работает только если ты понимаешь, что под капотом.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍85🔥2
☕️ ООП в Java: как писать поддерживаемый код, а не “инкапсуляция + наследование”

Ты не обязан учить ООП по книжке. Но обязан понимать, как структурировать код, чтобы его можно было:

🟢 расширять без боли,
🟢 не дублировать,
🟢 легко тестировать.

Вот как это делается в боевом коде 👇

📦 1. Интерфейсы = API, классы = реализация
public interface Storage {
void save(String data);
}

public class FileStorage implements Storage {
public void save(String data) {
// записать в файл
}
}

public class DBStorage implements Storage {
public void save(String data) {
// сохранить в БД
}
}

➡️ Теперь всё приложение работает с Storage, а не с FileStorage или DBStorage.
public class App {
private final Storage storage;

public App(Storage storage) {
this.storage = storage;
}

public void run() {
storage.save("some data");
}
}


👍 Меняешь реализацию — ничего не ломается. Архитектура устойчива.


🔄 2. Поведение через композицию, не через наследование
public class Logger {
public void log(String message) {
System.out.println("[LOG] " + message);
}
}

public class UserService {
private final Logger logger = new Logger();

public void register(String name) {
logger.log("Регистрация пользователя " + name);
}
}

➡️ Вместо extends Logger — просто вставили поведение. Гибче, проще, безопаснее.

🧩 3. Объекты = поведение, а не мешок полей
public class Order {
private final List<Product> products;

public Order(List<Product> products) {
this.products = products;
}

public BigDecimal total() {
return products.stream()
.map(Product::price)
.reduce(BigDecimal.ZERO, BigDecimal::add);
}
}

➡️ Объект умеет что-то делать, а не просто хранить данные. Это и есть "настоящее ООП".

⚙️ 4. Варианты поведения — через делегаты, не if/else
public interface DiscountPolicy {
BigDecimal apply(BigDecimal price);
}

public class NoDiscount implements DiscountPolicy {
public BigDecimal apply(BigDecimal price) {
return price;
}
}

public class BlackFridayDiscount implements DiscountPolicy {
public BigDecimal apply(BigDecimal price) {
return price.multiply(new BigDecimal("0.7"));
}
}


public class Checkout {
private final DiscountPolicy discount;

public Checkout(DiscountPolicy discount) {
this.discount = discount;
}

public BigDecimal finalPrice(BigDecimal basePrice) {
return discount.apply(basePrice);
}
}

➡️ Новый тип скидки? Просто добавь класс. Никаких switch/case/if.

🧠 Реальное ООП — это:

👍 контейнеры поведения с чётким контрактом,
👍 код, который расширяется, а не переписывается,
👍 минимум зависимостей, максимум гибкости,
👍 отделённые обязанности (SRP без декламации).


🗣️ Запомни:
ООП в Java — это не “инкапсуляция — наследование — полиморфизм”, а грамотно разложенные по объектам ответственности и поведение.
Если твой код не надо переписывать, чтобы добавить новый сценарий — это оно.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1710👨‍💻3
⌨️ Методы hashCode() и equals()

Методы hashCode() и equals() в Java тесно связаны и играют ключевую роль в работе хеш-структур, таких как HashMap, HashSet, Hashtable.

🔹 Метод equals(Object obj)

Этот метод определяет логическое равенство объектов. По умолчанию (Object.equals) сравниваются ссылки (то есть ==), но обычно его переопределяют, чтобы сравнивать содержимое объектов.

📜 Контракт equals:

1️⃣ Рефлексивностьx.equals(x) должно быть true.
2️⃣ Симметричностьx.equals(y)y.equals(x).
3️⃣ Транзитивностьx.equals(y) и y.equals(z)x.equals(z).
4️⃣ Согласованность — многократные вызовы x.equals(y) возвращают один и тот же результат, если объекты не меняются.
5️⃣ Сравнение с nullx.equals(null) должно быть false.


🔹 Метод hashCode()

Возвращает целое число, которое используется, например, для определения "корзины" (bucket) в хеш-таблицах.

📜 Контракт hashCode:

👍Если x.equals(y) — обязательно x.hashCode() == y.hashCode().
👍Обратное не обязательно: если x.hashCode() == y.hashCode(), это не значит, что x.equals(y).

🔄 Связь между equals и hashCode:
Если вы переопределяете equals(), вы обязательно должны переопределить и hashCode(), иначе, например, объект не будет корректно работать в HashSet или HashMap.

⛔️ Пример ошибки:

Set<Person> people = new HashSet<>();
people.add(new Person("Alice"));
System.out.println(people.contains(new Person("Alice"))); // false, если hashCode не переопределен


Правильный шаблон:

@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
Person person = (Person) obj;
return name.equals(person.name);
}

@Override
public int hashCode() {
return Objects.hash(name);
}
Please open Telegram to view this post
VIEW IN TELEGRAM
11👍7🔥2👏1
☕️ eBPF + JVM: мониторинг глубже, чем Prometheus

Хотите узнать, что реально происходит в Java‑приложении? eBPF открывает доступ к ядру Linux и даёт метрики и трассировку без переписывания кода или агентов.

В статье вы найдёте:

📌 Как eBPF и bpftrace помогают следить за GC, аллокациями и CPU
📌 Чем это глубже и точнее, чем обычный мониторинг
📌 Подводные камни и требования Linux 4.4+
📌 Почему это must‑have для high‑load Java

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

🗣️JVM больше не чёрный ящик: теперь вы реально видите, что происходит под капотом.

🤩 Java Фишки и трюки || #Cтатья
Please open Telegram to view this post
VIEW IN TELEGRAM
3👍2🔥2
🔥 Почему String в Java — immutable, и как это может неожиданно сломать тебе код?

Строки в Java неизменяемы — это значит, что любой метод replace(), substring(), toUpperCase() и даже += не изменяет строку, а создаёт новую.
Это кажется удобным... пока ты не врежешься в реальные проблемы.

🟢 Что значит immutable?
String s = "hello";
s.toUpperCase();
System.out.println(s); // hello

➡️ Ожидал "HELLO"? Не тут-то было. s.toUpperCase() вернул новую строку, но ты её никуда не сохранил.
Оригинальная строка осталась неизменной.

🟢 Почему так сделано?

1️⃣. Безопасность
Строки используются в ClassLoader, Map, URL, Reflection.
Если бы кто-то мог изменить строку "com.mysql.Driver" в рантайме — ты бы загрузил не тот класс.


2️⃣. Хеширование
String.hashCode() кешируется. Если строка изменилась бы после попадания в HashMap,
ты больше не смог бы её достать по ключу.


3️⃣. Thread Safety
Несколько потоков могут использовать одну строку одновременно — без блокировок и синхронизации.
Иммутабельность = потокобезопасность.


🧨 Где это реально ломает приложения?

📍 Ошибка 1: сравнение по == вместо equals()
String a = "test";
String b = new String("test");

System.out.println(a == b); // false
System.out.println(a.equals(b)); // true

➡️ == сравнивает ссылки, а не значения. Даже если строки одинаковые, объект может быть другим.

📍 Ошибка 2: изменение строки в цикле
String s = "";
for (int i = 0; i < 1000; i++) {
s += i;
}

➡️ Каждое += создаёт новую строку. 1000 операций = 1000 объектов = тормоза.
Правильно так:

StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; i++) {
sb.append(i);
}
String result = sb.toString();


📍 Ошибка 3: утечка памяти через substring()
String huge = "..." // большой текст
String small = huge.substring(0, 5);

➡️ small держал ссылку на huge — из-за чего вся большая строка не могла быть удалена.
Java это исправили, но в старых версиях боль реальна.

🗣️ Запомни: String — это надёжный, безопасный и вечно новый объект.
Хочешь модифицировать — используй StringBuilder или StringBuffer.
Хочешь сравнить — equals(), не ==.
Please open Telegram to view this post
VIEW IN TELEGRAM
10👍6🔥3
🌐 Как сделать HTTP-запрос в Java

Хочешь забирать данные из API, отправлять JSON, работать с HTTP в Java — и без боли? С Java 11 всё проще, потому что появился HttpClient, который умеет GET, POST, JSON, async — всё, что надо.

Вот разбор — пошагово и с примерами 👇

👍Шаг 1: Импорт нужных классов
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

➡️ Всё встроено в java.net.http, ничего не нужно скачивать.

👍 Шаг 2: Создаём клиента
HttpClient client = HttpClient.newHttpClient();

➡️ Это "браузер" внутри Java — он отправляет запросы, ждёт ответы и управляет соединениями.

👍 Шаг 3: Создаём GET-запрос
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.github.com"))
.build();

➡️ uri() — это URL запроса. Обязательно через URI.create(...).

👍 Шаг 4: Отправляем и получаем ответ
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.statusCode());
System.out.println(response.body());

➡️ send() — делает синхронный запрос.
➡️ BodyHandlers.ofString() — тело ответа как строка.

👍 Шаг 5: Отправка POST с JSON
String json = """
{
"name": "Alice",
"role": "admin"
}
""";

HttpRequest postRequest = HttpRequest.newBuilder()
.uri(URI.create("https://example.com/api/users"))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(json))
.build();

HttpResponse<String> postResponse = client.send(postRequest, HttpResponse.BodyHandlers.ofString());
System.out.println(postResponse.body());

➡️ Используем .POST() + BodyPublishers.ofString(...) для тела
➡️ Указываем Content-Type, чтобы сервер знал, что это JSON

👍 Шаг 6: Асинхронные запросы
client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
.thenApply(HttpResponse::body)
.thenAccept(System.out::println);

➡️ sendAsync() — не блокирует поток
➡️ Работает с CompletableFuture — можно делать цепочки

👍 Шаг 7: Обработка ошибок
try {
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 200) {
System.out.println(" Успех");
} else {
System.out.println(" Ошибка: " + response.statusCode());
}
} catch (Exception e) {
System.out.println("⚠️ Ошибка при запросе: " + e.getMessage());
}

➡️ Не забудь try/catch — HTTP может быть непредсказуемым


🗣️ Запомни: С HttpClient можно делать любые HTTP-запросы прямо из Java-кода.
Больше не нужно использовать громоздкий HttpURLConnection или сторонние библиотеки. Всё компактно и читаемо.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍162
☕️ Что такое Lombok и зачем он нужен

Если ты устал писать getters, setters, equals, toString, конструкторы и билдеры вручную — библиотека Lombok создана для тебя. Это мощный инструмент, который избавляет от шаблонного кода и делает Java-классы чище.

Вот как он работает и почему это стоит подключить уже сегодня 👇

🟢 Шаг 1: Что такое Lombok?

Lombokэто Java-библиотека, которая с помощью аннотаций генерирует код во время компиляции. Ты не видишь этих методов в коде, но они есть в .class-файле.

➡️ Экономит сотни строк кода и улучшает читаемость.

🟢 Шаг 2: Как подключить?

Для Maven:
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
<scope>provided</scope>
</dependency>

Для Gradle:
compileOnly 'org.projectlombok:lombok:1.18.30'
annotationProcessor 'org.projectlombok:lombok:1.18.30'

📌 Также убедись, что у тебя установлен Lombok plugin в IntelliJ IDEA / Eclipse!

🟢 Шаг 3: Убираем шаблонный код

Без Lombok:
public class User {
private String name;
private int age;

public String getName() { return name; }
public void setName(String name) { this.name = name; }

public int getAge() { return age; }
public void setAge(int age) { this.age = age; }

@Override
public String toString() {
return "User{name='" + name + "', age=" + age + "}";
}
}

С Lombok:
import lombok.Data;

@Data
public class User {
private String name;
private int age;
}

➡️ Всё то же самое, но в 3 строки! @Data создаёт:
get/set, toString(), equals(), hashCode() и конструктор по умолчанию.

Часто используемые аннотации Lombok
@Getter @Setter         // Только геттеры и сеттеры
@NoArgsConstructor // Пустой конструктор
@AllArgsConstructor // Конструктор со всеми полями
@RequiredArgsConstructor // Только для final / @NonNull полей
@Builder // Шаблон Builder
@ToString // Авто toString()
@EqualsAndHashCode // equals() + hashCode()
@Value // Immutable класс (все final)

➡️ Всё это убирает десятки строк шаблонного кода.

🟢 Пример с @Builder
import lombok.Builder;
import lombok.ToString;

@Builder
@ToString
public class Product {
private String name;
private double price;
private boolean available;
}

Product p = Product.builder()
.name("MacBook")
.price(2499.99)
.available(true)
.build();

System.out.println(p);

➡️ Идеально для создания объектов с множеством параметров.


🗣️ Запомни: Lombok — это не магия, а компиляция. Он просто пишет за тебя шаблонный код.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍142😇2
☕️ Как работает Lombok под капотом.

Lombok кажется магией: пишешь @Getter, @Builder, @Slf4j — и бац, всё работает. Но на самом деле он не добавляет методы во время выполнения. Всё происходит на этапе компиляции, и ты даже можешь это увидеть.

🟢 Что реально происходит с @Getter
@Getter
public class User {
private String name;
}

➡️ Во время компиляции Lombok встраивает в AST (абстрактное синтаксическое дерево) метод:
public String getName() {
return this.name;
}

➡️ То есть ты этого в коде не видишь, но javac уже получил готовый getName(), как будто ты сам его написал.


🟢 Где именно это происходит
Lombok использует Javac-плагины и работает как annotation processor. Он подключается в javac через SPI (Service Provider Interface) и внедряется в процесс разбора исходного кода — до того, как он станет байткодом.

➡️ Это не runtime, а compile-time магия.

🟢 Почему это работает в IDE
IntelliJ IDEA и Eclipse поддерживают Lombok через плагины. Они умеют подхватывать изменения AST от Lombok, и даже подсвечивать методы, которые физически не написаны.

➡️ Без плагина IDEA не увидит методов, и всё будет красным.


🟢 Пример: что генерирует @Builder
@Builder
public class Book {
private String title;
private int pages;
}

➡️ Под капотом Lombok добавляет

public static class BookBuilder {
private String title;
private int pages;

public BookBuilder title(String title) {
this.title = title;
return this;
}

public BookBuilder pages(int pages) {
this.pages = pages;
return this;
}

public Book build() {
return new Book(title, pages);
}
}

➡️ И плюс метод Book.builder() — точка входа.


🟢 Хочешь увидеть это сам?

Скомпилируй Lombok-класс и деобфусцируй .class:
javac Book.java
javap -p Book.class

➡️ Ты увидишь, что методы реально есть, просто их не было в твоём .java-файле.

🗣 Запомни: Lombok — это макросы на этапе компиляции, а не runtime-библиотека.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍97🔥6
⚙️ Java 25: долгожданный LTS и революция в многопоточности

Java не стоит на месте: версия 25 выходит уже этой осенью и принесёт не просто косметические изменения, а реально новые возможности для удобного, быстрого и современного кода. Если вы считали Java «тяжеловесом» — самое время пересмотреть взгляд!

В статье вы найдёте:

📌 Краткий разбор фич Java 25: pattern matching для примитивов, structured concurrency, compact object headers
📌 Как Project Loom меняет подход к потокам в реальных приложениях
📌 Что дают Value Types и Scoped Values для читаемости и производительности
📌 Новые инструменты профилирования: CPU‑time в JFR, AOT‑profiling и др.
📌 Рекомендации, как безболезненно перейти на новую версию

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

🗣️ Java больше не просто классика: это современный, лаконичный и быстрый инструмент для продвинутой разработки.

🤩 Java Фишки и трюки || #Cтатья
Please open Telegram to view this post
VIEW IN TELEGRAM
😇7👍5
🧠 Rate Limiter на Java без Spring — с нуля, по шагам, с мозгами

Когда у тебя API, бот, сервер или утилита — нужно ограничивать частоту запросов, чтобы никто не зафлудил систему.
Решение — Rate Limiter. Ни Spring, ни Guava не нужны. Всё делаем на чистом Java.

📁 Шаг 🔢: создаём лимитер с окном по времени
Идея простая: мы храним время всех недавних запросов и выкидываем те, что вышли за окно (например, 10 секунд назад).
class RateLimiter {
private final int limit;
private final long windowMs;
private final Deque<Long> timestamps = new ArrayDeque<>();

public RateLimiter(int limit, long windowSeconds) {
this.limit = limit;
this.windowMs = windowSeconds * 1000;
}

public synchronized boolean allow() {
long now = System.currentTimeMillis();
// Удаляем старые запросы
while (!timestamps.isEmpty() && now - timestamps.peek() > windowMs) {
timestamps.poll();
}
// Проверка лимита
if (timestamps.size() < limit) {
timestamps.add(now);
return true;
}
return false;
}
}

➡️ Здесь limit — количество запросов, windowSeconds — время в секундах.
Всё хранится в памяти. Работает моментально, идеально для локального контроля.

📁 Шаг 🔢: подключаем к логике запроса

Представим, у тебя HTTP-сервер или обработчик:
RateLimiter limiter = new RateLimiter(5, 10); // 5 запросов на 10 сек

public void handleRequest() {
if (limiter.allow()) {
System.out.println(" Запрос принят");
} else {
System.out.println(" 429 Too Many Requests");
}
}

➡️ За секунду можно накидать 5 успешных запросов, шестой — будет заблокирован. Через 10 секунд — снова 5 доступных.


📁 Шаг 🔢: делаем лимиты на пользователя / IP / ключ

Чтобы не глобально, а по каждому клиенту — оборачиваем RateLimiter в Map.
Map<String, RateLimiter> userLimits = new ConcurrentHashMap<>();

public boolean allowRequest(String userId) {
userLimits.putIfAbsent(userId, new RateLimiter(10, 30));
return userLimits.get(userId).allow();
}

➡️ Теперь у каждого клиента — свой лимит. IP → лимитер, токен → лимитер, логин → лимитер.

📁 Шаг 🔢: многопоточность и защита
Так как у нас ConcurrentHashMap и synchronized внутри лимитера — решение уже потокобезопасное. Можно сразу использовать в многопоточных веб-приложениях или TCP-серверах.


📁 Шаг 🔢: нагрузочное тестирование

Вот что будет, если послать много запросов:
for (int i = 0; i < 20; i++) {
boolean ok = limiter.allow();
System.out.println(i + " -> " + (ok ? "" : ""));
Thread.sleep(1000);
}

➡️ Первые 5 — пройдут. Потом 10 . Потом снова пойдут ✔️ по мере освобождения окна. Всё по-честному.

🗣️ Запомни:Rate Limiter — это простая логика, но если её нет — ты труп под первым же флотом запросов.Лимиты = защита = стабильность. Не жди DDoS, внедряй заранее.
Please open Telegram to view this post
VIEW IN TELEGRAM
12🔥7👍5
⌨️ Maven. Фазы и команды

Maven использует жизненный цикл сборки, который делится на несколько фаз. Фазы определяют последовательность задач, которые Maven выполняет для сборки и управления проектом.

Основные фазы жизненного цикла Maven включают:

1️⃣ validate – Проверяет, что проект правильный и вся необходимая информация указана.

2️⃣ compile – Компилирует исходный код проекта.

3️⃣ test – Запускает тесты (обычно с использованием JUnit или TestNG) и проверяет, что они проходят успешно.

4️⃣ package – Собирает скомпилированный код и пакует его, например, в JAR или WAR-файл.

5️⃣ verify – Проверяет собранные артефакты и результаты тестов.

6️⃣ install – Устанавливает пакет в локальный репозиторий для использования как зависимость в других проектах.

7️⃣ deploy – Отправляет финальный пакет в удаленный репозиторий для использования в других проектах или на сервере.

Основные команды Maven:

✔️ mvn clean – Удаляет папку target, очищая проект от предыдущих сборок.

✔️ mvn compile – Компилирует исходный код проекта.

✔️ mvn test – Запускает тесты.

✔️ mvn package – Пакует скомпилированный код в конечный артефакт (обычно JAR или WAR).

✔️ mvn install – Устанавливает артефакт в локальный репозиторий.

✔️ mvn deploy – Деплоит артефакт в удаленный репозиторий.

✔️ mvn site – Генерирует документацию проекта на основе кода и зависимостей.


Фазы выполняются последовательно, то есть если вы запускаете команду mvn install, Maven автоматически пройдет через все предыдущие фазы – от validate до install.

Примеры команд:

✔️ mvn clean install – очищает проект, компилирует, тестирует и устанавливает артефакт в локальный репозиторий.

✔️ mvn package -DskipTests – собирает проект в артефакт, пропуская тесты.

#java #Maven
Please open Telegram to view this post
VIEW IN TELEGRAM
👍183🔥3
⚡️ Static Initializer Hack в Java — выполняем код при загрузке класса

Java даёт способ выполнить код один раз, ещё до создания объекта. Это называется static initializer — и с ним можно делать настоящие фокусы 👇

🔁 Что это вообще такое

Когда JVM загружает класс — выполняются все static-блоки, даже если ты не создавал ни одного объекта.

Это можно использовать для:


🟢 регистрации классов
🟢 скрытой инициализации
🟢 запуска кода без main()
🟢 взлома "одиночек" или подмены поведения

📦 Простой пример static-блока
public class Hello {
static {
System.out.println("Загрузка Hello");
}

public static void main(String[] args) {
System.out.println("main()");
}
}


➡️ Вывод:
Загрузка Hello
main()

🟢 Сначала сработал static-блок, потом вызвался main.

💣 Выполнение кода без main()
public class RunOnce {
static {
System.out.println("Код запустился без main()");
System.exit(0); // JVM завершится
}
}

🟢 При запуске RunOnce.class — код выполнится, и main() даже не потребуется.

🧠 Применение: регистрация классов
interface Plugin {
void run();
}

class Registry {
static List<Plugin> plugins = new ArrayList<>();
static void register(Plugin p) {
plugins.add(p);
}
}

public class PluginA implements Plugin {
static {
Registry.register(new PluginA());
}

public void run() {
System.out.println("Плагин A запущен");
}
}


🟢 Просто загрузив PluginA, ты уже зарегистрировал его — без явного вызова конструктора или методов.

🧪 Хак с подменой поведения
class Evil {
static {
System.setSecurityManager(null); // отключаем защиту
}
}

🟢 Опасная штука — используется при обходе sandbox'а или во взломе.
Подгружаешь Evil.class, и твой код внезапно без ограничений.


💬 Хочешь пост про Unsafe, Objenesis или про bytecode-инъекции? Пиши тему — сделаем с практикой.

🗣️ Запомни:Если ты понимаешь когда и зачем срабатывает static-блок — ты уже на шаг ближе к JVM-магию ☄️
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14🔥5😇32👏1
🧰 Маппинг Enum по String без if/switch: делаем Map

Классика: приходит строка "ACTIVE" — надо получить Status.ACTIVE. Но вместо кучи if или switch — строим быстрый и красивый Map-мэппинг, который работает за O(1) и не ломается при добавлении новых enum.

Вот как это сделать правильно 👇

🟢 Enum с кодом
public enum Status {
ACTIVE("active"),
BLOCKED("blocked"),
DELETED("deleted");

private final String code;
Status(String code) { this.code = code; }
public String getCode() { return code; }
}

➡️ Мы явно задали code, который будет использоваться для маппинга (например, из JSON, БД или UI).

🟢 Создаём Map один раз
public class StatusMapper {
private static final Map<String, Status> CODE_MAP = Arrays.stream(Status.values())
.collect(Collectors.toMap(Status::getCode, Function.identity()));

public static Status fromCode(String code) {
return CODE_MAP.get(code);
}
}

➡️ При первом запуске строим Map<String, Status>, где ключ — это status.getCode(), а значение — сам enum.

🧪 Использование:
Status status = StatusMapper.fromCode("active");
System.out.println(status); // ACTIVE

➡️ Работает мгновенно и безопасно. Без цепочек if, без null, без ошибок при добавлении новых значений.

🛡 Добавим защиту от невалидных значений:
public static Status fromCode(String code) {
Status result = CODE_MAP.get(code);
if (result == null) {
throw new IllegalArgumentException("Unknown status: " + code);
}
return result;
}

➡️ Код теперь fail-fast. Любое неожиданное значение сразу бросит ошибку — удобно в API и при валидации.

🗣️ Запомни: Enum.name() и Enum.toString() — не для бизнес-логики. Маппинг через Map — самый быстрый и читаемый способ.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍165🔥2👏1😇1
🧨 Unsafe в Java: прямой доступ к памяти (и да — это реально работает)

Java — безопасный язык, пока ты не подключаешь Unsafe. Это внутренний API из JDK, который даёт доступ к памяти как в C: ты можешь читать, писать, аллоцировать и даже обойти конструкторы. Без всяких JVM-защит.

Не использовать в проде без необходимости. Но как концепт — огонь.

📦 Получаем доступ к Unsafe (через костыль)
Field f = Unsafe.class.getDeclaredField("theUnsafe");
f.setAccessible(true);
Unsafe unsafe = (Unsafe) f.get(null);

➡️ Это приватное поле, поэтому нужен рефлекс. С Java 12 и выше понадобится --add-opens, но в старых версиях работает напрямую.

💥 Аллокация памяти вручную
long address = unsafe.allocateMemory(8); // 8 байт
unsafe.putLong(address, 123456789L); // запись
long value = unsafe.getLong(address); // чтение

System.out.println(value); // 123456789

unsafe.freeMemory(address); // ручной free

➡️ Как malloc/free. Память вне кучи (off-heap), GC её не видит.

🧬 Доступ к полям объекта по смещению
class Demo {
private int secret = 42;
}

Demo d = new Demo();
Field field = Demo.class.getDeclaredField("secret");
long offset = unsafe.objectFieldOffset(field);

unsafe.putInt(d, offset, 99); // меняем приватное поле

System.out.println(unsafe.getInt(d, offset)); // 99

➡️ Меняем приватные поля БЕЗ сеттеров и даже без setAccessible.

🚫 Обход конструктора: создаём объект без new
class NoConstructor {
private NoConstructor() {
throw new RuntimeException("Don't call me");
}
}

NoConstructor obj = (NoConstructor) unsafe.allocateInstance(NoConstructor.class);
System.out.println(obj);

➡️ JVM не вызывает конструктор вообще. Объект появляется из воздуха.

🧠 Прямое управление массивами
int[] arr = new int[10];
long base = unsafe.arrayBaseOffset(int[].class);
int scale = unsafe.arrayIndexScale(int[].class);

unsafe.putInt(arr, base + scale * 5, 99); // пишем в arr[5]
System.out.println(arr[5]); // 99

➡️ Как pointer arithmetic в C. У тебя есть offset и шаг (scale).

✔️ Используй Unsafe, чтобы:

🟢 делать off-heap кэш/пулы
🟢 изменять приватные данные в рантайме
🟢 писать кастомные структуры данных
🟢 встраивать C-подобные трюки в Java


🗣️ Запомни: Это выход за пределы JVM-санбокса. Но иногда он даёт то, что невозможно сделать иначе. Unsafe — это как ядро Java-хакерства. У него огромная сила, но и риск.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥8👍74😈3😇1
☕️ JDK 24 ускоряет Java-бэкенд: от виртуальных потоков до операций с FFM

Нашёл одну свежую и реально интересную статью — обзор Performance Improvements in JDK 24 от Inside.java (март 2025). В ней рассказывается о конкретных улучшениях, которые уже влияют на скорость приложений.

В статье вы найдёте:

📌 Оптимизация «bulk operations» в Foreign Function & Memory API — быстрее копирование и заполнение сегментов
📌 MergeStore в JIT — меньше операций записи, выше скорость работы с массивами
📌 Ускоренный startup через скрытые классы для конкатенации строк
📌 +27 % ускорения хеширования с SHA‑3
📌 Доработки виртуальных потоков: снятие pinning, лучшая синхронизация
📌 Что полезного для разработчиков: всё это работает «из коробки» — без переписывания кода
📌 Как это помогает писать код лучше: меньше задержек, быстрее прод, внимание разработчика уходит в логику, а не оптимизацию

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

🗣️ JDK‑24 — это не просто новая версия, а реальный прирост скорости для вашего продакшена.

🤩 Java Фишки и трюки || #Cтатья
Please open Telegram to view this post
VIEW IN TELEGRAM
9👍7👏2
🧩 Marker + Default methods: интерфейсы как конфигурация, без аннотаций и свитчей

Ты можешь использовать интерфейсы не как API, а как декларативную конфигурацию — через маркер + дефолтные методы. Без if-else, без флагов, без switch.

📛 Маркер как флаг
public interface Debuggable {} // пустой интерфейс


➡️ Никакой логики, просто метка. Если класс его реализует — значит, он отлаживаемый.

public class Service implements Debuggable {}


💡 Теперь достаточно instanceof:
void log(Object o) {
if (o instanceof Debuggable) {
System.out.println("🐞 Включаем отладку");
}
}

➡️ Никаких .isDebug(), никаких аннотаций — только тип.

🛠 Дефолтные методы — поведение по умолчанию
public interface HasTimeout {
default int getTimeout() {
return 1000; // мс
}
}


Ты получаешь “конфигурацию по умолчанию”, которую можно переопределить:
public class FastRequest implements HasTimeout {
@Override
public int getTimeout() {
return 100;
}
}

public class NormalRequest implements HasTimeout {
// будет 1000 по умолчанию
}


void send(HasTimeout req) {
System.out.println("⌛️ Таймаут: " + req.getTimeout());
}

➡️ Без config-файлов, без if (instanceof) — всё в типе.

📦 Конфигурация как набор интерфейсов
public interface RequiresAuth {
default boolean isAuthRequired() {
return true;
}
}

public interface ReturnsJson {
default String contentType() {
return "application/json";
}
}


➡️ И теперь просто пишешь:
public class ApiCall implements RequiresAuth, ReturnsJson {}


void handle(Object call) {
if (call instanceof RequiresAuth auth && auth.isAuthRequired()) {
System.out.println("🔐 Проверка токена");
}
if (call instanceof ReturnsJson rj) {
System.out.println("📤 JSON-ответ: " + rj.contentType());
}
}

➡️ Тип сам диктует поведение. Без логики — просто наличие интерфейса.


📚 Даже enum можно конфигурировать
public interface Critical {}

public enum Action implements Critical {
DELETE_ALL, RESET_DB
}


void execute(Enum<?> action) {
if (action instanceof Critical) {
System.out.println("🚨 ВНИМАНИЕ: опасная операция");
} else {
System.out.println(" Безопасно");
}
}

➡️ Enum + интерфейс = мощная типовая декларация.


🗣️ Запомни: Marker + Default methods = тип как конфигурация. Ты пишешь код, который читает сам себя. Поведение не через данные, а через тип.Меньше if, меньше флагов, больше ясности.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥163👍3
🧪 Создание объекта без конструктора — это реально

В Java обычно new вызывает конструктор. Но можно создать объект, вообще не вызывая ни один конструктор. Даже private, даже если он кидает исключения.

Это работает через ☠️ Unsafe или ✔️ Objenesis.

☠️ Unsafe: объект без жизни
class User {
private User() {
throw new RuntimeException("нельзя вызывать");
}
}

Unsafe unsafe = ...;
User user = (User) unsafe.allocateInstance(User.class);

➡️ Объект создан. Конструктор не сработал.
➡️ Все поля — нули, даже final.

Ты просто получил кусок памяти под User, но без инициализации.

Objenesis: библиотека для этого
Objenesis objenesis = new ObjenesisStd();
User user = objenesis.newInstance(User.class);

➡️ Тоже создаёт объект без конструктора.
➡️ Работает на всех JVM, без хака Unsafe.
➡️ Поддерживается, используется в Spring, Mockito, Kryo.

📦 Maven-зависимость:
<dependency>
<groupId>org.objenesis</groupId>
<artifactId>objenesis</artifactId>
<version>3.3</version>
</dependency>


📛 Где это используют

Hibernate, Jackson, Kryo, Mockito — создают объекты из JSON или прокси без вызова конструктора.
Ты можешь сделать то же:
class Secret {
private final int x = 42;
private Secret() {
throw new IllegalStateException("нельзя");
}
}

Secret s = (Secret) unsafe.allocateInstance(Secret.class);
System.out.println(s.x); // 0, даже final не работает

➡️ Конструктор не вызвался, даже final сброшен.

🗣 Запомни:Ты можешь создать любой объект — даже если конструктор кидает ошибку.
Просто
Unsafe.allocateInstance(Class) или objenesis.newInstance(Class).
Но инициализировать поля придётся самому.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥6👍43👏1
Media is too big
VIEW IN TELEGRAM
☕️ Установка JDK и IDE.

В этом видео автор простым и понятным языком демонстрирует установку Java с нуля — от загрузки JDK до настройки среды разработки (IDE). Всё показано пошагово: выбор инструментария, установка, проверка работоспособности.Это отличный старт, если ты только начинаешь изучать Java и хочешь настроить всё правильно с самых основ.


🤩 Java Фишки и трюки || #Видео
Please open Telegram to view this post
VIEW IN TELEGRAM
👍83
JDBC 🆚 Hibernate: как Java работает с базами — и чем это тебе грозит

Java умеет работать с БД как вручную (через JDBC), так и “по-умному” (через Hibernate/JPA).
Один путь — контроль и боль. Второй — магия и её последствия.
Разберём всё по фактам, на живых примерах 👇

🔌 JDBC — низкоуровневый доступ через SQL
Connection conn = DriverManager.getConnection(url, user, pass);
PreparedStatement stmt = conn.prepareStatement("SELECT * FROM users WHERE id = ?");
stmt.setInt(1, 42);
ResultSet rs = stmt.executeQuery();

while (rs.next()) {
System.out.println(rs.getString("name"));
}

🟢 Всё вручную: от подключения до маппинга.
🟢 Полный контроль, но каждый чих — в 5 строк.
🟢 Если ты решил добавить JOIN — добро пожаловать в SQL-приключения.

🏗 Hibernate / JPA — ORM и сущности
@Entity
public class User {
@Id
private Long id;
private String name;
}


User user = entityManager.find(User.class, 42L);

🟢 SQL скрыт под капотом, данные — это Java-объекты.
🟢 Быстро, декларативно, красиво.
🟢 Но ты больше не контролируешь, что именно улетает в базу.

💥 Пример боли: Lazy vs Eager
@Entity
public class Post {
@ManyToOne(fetch = FetchType.LAZY)
private User author;
}


Post post = postRepo.findById(1L).get();
System.out.println(post.getAuthor().getName()); // 💣 LazyInitializationException

🟢 Если сессия закрыта — Hibernate не подгрузит данные.
🟢Работает только внутри транзакции.
🟢 Или делай JOIN FETCH, или не забывай про открытые сессии.

🛠 Spring + JPARepository — удобный уровень
public interface UserRepo extends JpaRepository<User, Long> {
List<User> findByName(String name);
}

➡️ Никаких SQL, методы создаются из названия.
➡️ CRUD, пагинация, фильтры — всё из коробки.
➡️ Но если нужен ручной SQL — Spring Data позволяет это тоже:

@Query("SELECT u FROM User u WHERE u.name LIKE %:name%")
List<User> search(@Param("name") String name);


⚙️ JdbcTemplate — между ручным и магическим
List<User> users = jdbcTemplate.query(
"SELECT * FROM users",
(rs, rowNum) -> new User(rs.getLong("id"), rs.getString("name"))
);

➡️ Ты пишешь SQL, но не паришься с ResultSet.
🟢 Оптимально для кастомных запросов.

🧪 Тестирование — через @DataJpaTest и H2
@DataJpaTest
class RepoTest {
@Autowired UserRepo repo;

@Test
void testSave() {
repo.save(new User("Test"));
assertTrue(repo.findByName("Test").size() > 0);
}
}

➡️ H2 работает в памяти, быстро поднимается и убивается.
🟢 Подходит для unit+integration тестов одновременно.

🗣️ Запомни: JDBC — как нарезать салат вручную: аккуратно, но долго. Hibernate — как блендер: быстро, но иногда не туда. Выбирай по задаче, а не по вкусу архитектора.
Please open Telegram to view this post
VIEW IN TELEGRAM
10👍9🔥4😇1