Java Ready | Программирование
8.95K subscribers
1.37K photos
75 videos
1 file
718 links
Авторский канал по разработке на Java.
Ресурсы, гайды, задачи, шпаргалки.
Информация ежедневно пополняется!

Автор: @energy_c

Реклама на бирже: https://telega.in/c/java_ready
Download Telegram
Шпаргалка по Maven!

Например, mvn test запускает тесты, mvn package собирает артефакт, а mvn dependency:tree показывает дерево зависимостей проекта.
На картинке основные Maven-команды, фазы lifecycle, полезные параметры командной строки, локальный репозиторий, Maven Central и популярные плагины: help, dependency, compiler, version, wrapper, Spring Boot и exec.

Сохрани, чтобы не потерять!

👉 Java Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
12👍7🔥6
Разбираем Sequenced Collections!

В Java 21 появился общий API для коллекций, у которых есть понятный порядок элементов: первый, последний и обратный обход. Раньше для этого приходилось помнить разные методы у List, Deque, LinkedHashMap и других структур.

👉 Java Ready | #шпора
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥10👍76
Статья про E2EE-мессенджер на Spring Boot и WebCrypto!

Автор показывает, как устроить сквозное шифрование так, чтобы сервер передавал сообщения, но не видел их содержимое.

В статье автор показывает:
• как устроена сессия и обмен ключами
• зачем нужен ratchet-подход для сообщений
• какие архитектурные ошибки легко допустить при E2EE

Продолжай читать на Habr!


👉 Java Ready | #статья
Please open Telegram to view this post
VIEW IN TELEGRAM
8🔥5👍3🤝2
Делаем простой HTTP-запрос через HttpClient!

Иногда нужно без сторонних библиотек сходить в API, получить JSON или проверить доступность. Начиная с Java 11 для этого есть встроенный HttpClient.

Сначала создадим клиент:
HttpClient client = HttpClient.newHttpClient();


Теперь соберём request:
HttpRequest request = HttpRequest.newBuilder()


Укажем адрес:
.uri(URI.create("https://api.github.com"))


Выберем GET-запрос:
.GET()


И соберём объект:
.build();


Ответ можно получить синхронно:
var response = client.send(request,
HttpResponse.BodyHandlers.ofString());


Код статуса лежит отдельно:
System.out.println(response.statusCode());


Тело ответа можно прочитать так:
System.out.println(response.body());


Для реального кода почти всегда стоит добавить timeout. Тогда запрос не сможет зависнуть навсегда:
.timeout(Duration.ofSeconds(5))


Если запросов много, клиент лучше переиспользовать. Он потокобезопасный и нормально подходит для сервисов, CLI-утилит и фоновых задач.

Такой подход удобен, когда нужно быстро сделать интеграцию без OkHttp, Apache HttpClient и других зависимостей.

👉 Java Ready | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
👍125🔥5
Почему ThreadLocal нужно чистить после использования?

ThreadLocal удобен, когда значение должно быть привязано к конкретному потоку:
private static final ThreadLocal<String> USER_ID =
new ThreadLocal<>();


Например, в начале обработки запроса можно сохранить id пользователя:
USER_ID.set("user-42");


А ниже по коду достать его без передачи через каждый метод:
String userId = USER_ID.get();


Но в серверных приложениях потоки часто переиспользуются пулом.

Если значение не удалить, следующий запрос может попасть на тот же поток и увидеть старые данные.

Поэтому после работы важно очищать ThreadLocal:
try {
USER_ID.set(userId);
handleRequest();
} finally {
USER_ID.remove();
}


finally нужен, чтобы очистка сработала даже при исключении.

👉 Java Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
8👍2🔥2🤝2
Собираем сортировку задач по зависимостям!

Нужно получить порядок выполнения задач, где одна задача может зависеть от другой. Например, сначала build, потом test, а deploy только после test.

В этой задаче:
• описываем граф зависимостей
• считаем входящие связи
• кладём свободные задачи в очередь


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

👉 Java Ready | #задача
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
2👍1🔥1
Почему Collections.unmodifiableList не делает настоящую копию?

В Java часто нужно отдать список наружу так, чтобы вызывающий код не мог его изменить. Например, из getter-метода, DTO, настроек или внутреннего состояния сервиса.

Для этого часто используют Collections.unmodifiableList.
List<String> roles = new ArrayList<>();
List<String> view = Collections.unmodifiableList(roles);


Через view действительно нельзя вызвать add или remove. Такой вызов закончится исключением.

Но важный нюанс в том, что unmodifiableList создаёт не копию, а представление поверх исходного списка.

Если изменить оригинальный список, изменения будут видны и через view.
roles.add("admin");
System.out.println(view);


На экране появится новое значение, хотя сам view вроде бы неизменяемый. Он просто запрещает менять список через себя, но не защищает от изменений оригинала.

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

Если нужна именно независимая копия, лучше использовать List.copyOf.
List<String> snapshot = List.copyOf(roles);


Теперь snapshot не связан с дальнейшими изменениями исходного списка. Это уже снимок состояния на момент создания.

Разница особенно заметна в классах с внутренним состоянием.
class User {
private final List<String> roles = new ArrayList<>();

List<String> roles() {
return List.copyOf(roles);
}
}


Так вызывающий код получает безопасный результат и не может случайно повлиять на объект изнутри.

Если элементы списка сами изменяемые, копия списка не делает глубокую копию элементов. Например, список объектов UserRole всё ещё будет содержать те же самые объекты.

Поэтому для настоящей неизменяемости важно думать не только о коллекции, но и о типах внутри неё. Для строк, чисел, enum и record-объектов такой подход обычно работает хорошо.

Плохой вариант выглядит так.
class User {
private final List<String> roles;

User(List<String> roles) {
this.roles = roles;
}
}


Если внешний код сохранит ссылку на исходный список, он сможет поменять состояние объекта уже после создания.

Безопаснее делать defensive copy прямо в конструкторе.
this.roles = List.copyOf(roles);


Тогда объект получает своё стабильное состояние. Даже если исходный список потом очистят или дополнят, поле внутри User не изменится.

👉 Java Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
7🔥7👍5
Шпаргалка по устройству JVM!

Например, Heap хранит объекты и делится на young/old generation, а Stack содержит фреймы вызовов, локальные переменные и работает отдельно для каждого потока.

На картинке основные области памяти JVM: Heap, Stack, Metaspace, PC Register и Native Method Stack, а также краткая логика работы GC и сравнение популярных сборщиков мусора.

Сохрани, чтобы не потерять!

👉 Java Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
👍75🔥5
This media is not supported in your browser
VIEW IN TELEGRAM
Очнись, нас готовят к цифровому ГУЛАГу

Уже в десятках регионов России отключают мобильный интернет (даже когда нет атак БПЛА), тестируют «белые списки» и замедляют Телегу.

90% людей тупо смотрят на уплывающий корабль свободного Интернета. Люди поумнее готовятся к новой реальности и читают «Пакет Безопасности».

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

Без шуток, сейчас это один из самых полезных каналов в Телеге. Надеемся на лучшее, но к чему нужно готовиться — вы и сами понимаете: @package_security
👎6
Как в Java чище проверять тип через pattern matching?

Раньше при проверке типа часто писали так:
if (value instanceof String) {
String text = (String) value;
System.out.println(text.length());
}


Код рабочий, но в нём есть лишнее приведение типа. Сначала Java уже проверила, что value это String, а потом мы всё равно руками делаем cast.

В современном Java можно записать короче:
if (value instanceof String text) {
System.out.println(text.length());
}


Переменная text доступна только там, где проверка точно прошла.

Это удобно для валидации:
if (input instanceof String text && !text.isBlank()) {
return text.trim();
}


И для обработки разных входных объектов:
if (event instanceof LoginEvent login) {
audit(login.userId());
}


При этом Java не даст использовать переменную вне безопасной области:
if (!(value instanceof String text)) {
return;
}

System.out.println(text.length());


Здесь text уже доступен после return, потому что дальше код дойдёт только если value действительно String.

Такой синтаксис особенно приятен в коде с Object, событиями, DTO, sealed-иерархиями и обработкой внешних данных.

👉 Java Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥54👍4