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

Автор: @energy_it

Реклама на бирже: https://telega.in/c/java_ready
Download Telegram
This media is not supported in your browser
VIEW IN TELEGRAM
✍️ Gizmo AI — нейросеть для обучения и запоминания информации!

AI-сервис, который помогает превращать заметки, PDF, статьи, видео и другие материалы в карточки для обучения и квизы. Нейросеть автоматически выделяет главное, генерирует вопросы и помогает быстрее запоминать информацию с помощью повторения и интерактивного формата обучения.

📌 Оставляю ссылочку: gizmo.ai

👉 Java Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥103👍2
Знаете, что в Java можно сделать неизменяемую копию коллекции?

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

Например:
List<Long> ids = new ArrayList<>();
ids.add(10L);
ids.add(20L);

process(ids);


Если внутри process() кто-то вызовет clear() или add(), исходный список тоже изменится.

Для таких случаев удобно использовать copyOf():
List<Long> safeIds = List.copyOf(ids);


Теперь safeIds нельзя изменить:
safeIds.add(30L); // UnsupportedOperationException


То же самое есть у Set и Map:
Set<Long> uniqueIds = Set.copyOf(ids);

Map<String, Integer> copy = Map.copyOf(stats);


Это полезно для DTO, настроек, прав доступа, списков ID, результатов из базы и любых данных, которые после создания не должны меняться.

Важно: copyOf() делает коллекцию неизменяемой, но если внутри лежат mutable-объекты, сами эти объекты всё ещё можно менять.
List<User> users = List.copyOf(originalUsers);


Здесь нельзя добавить нового User в список, но можно изменить поля существующего объекта, если сам User изменяемый.

👉 Java Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
9👍7🔥4
📂 Напоминалка по HTTP/2 и HTTP/3!

Например, HTTP/2 работает поверх TCP и мультиплексирует запросы через одно соединение, а HTTP/3 использует QUIC поверх UDP и избавляется от Head-of-Line Blocking между потоками.

На картинке — простое сравнение HTTP/2 и HTTP/3: как работают streams, почему TCP может тормозить все запросы сразу.

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

👉 Java Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥95👍4
Создание CSV-файла с данными!

CSV — самый простой формат хранения таблиц. Строки это записи, значения разделяются запятыми. Java позволяет создать такой файл без библиотек.

Готовим список строк, которые попадут в CSV:
var rows = java.util.List.of(
"name,age,city",
"Alice,22,Paris",
"Bob,30,Berlin"
);


Преобразуем строки в единый текст:
var csv = String.join("\n", rows);


Сохраняем CSV-файл в проект:
java.nio.file.Files.writeString(
java.nio.file.Path.of("users.csv"),
csv
);


🔥 В итоге получаем готовый файл users.csv, который можно открыть в Excel, Numbers или Google Sheets.

👉 Java Ready | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
7👍2🔥2
😎 Хочешь понять, как Java-сервис поведёт себя под нагрузкой ещё до релиза? Тогда эта статья тебе точно пригодится!

В ней ты узнаешь:
• Как использовать Virtual Threads для запуска большого количества задач
• Как локально имитировать нагрузку на сервис
• Как смотреть, где приложение упирается в память, CPU или базу данных
• Как собирать простые метрики во время теста


Продолжай читать на Хабре!


👉 Java Ready | #статья
Please open Telegram to view this post
VIEW IN TELEGRAM
6🔥4👍3
📂 Шпаргалка по аннотациям Spring Boot!

Например, @RestController используется для создания REST API, @Autowired — для внедрения зависимостей, а @Transactional помогает управлять транзакциями.

На картинке — основные аннотации Spring Boot, Spring MVC, JPA, Security, Validation и тестирования, которые чаще всего используются в реальных проектах.

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

👉 Java Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
20👍11🔥6
Знаете, что в Java можно безопасно создать файл и не перезаписать старый?

Обычно при записи легко случайно затереть существующий файл:
Files.writeString(path, json);


Если файл уже есть, его содержимое будет заменено.

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

В таких случаях можно использовать
StandardOpenOption.CREATE_NEW:

Files.writeString(path, json, StandardOpenOption.CREATE_NEW);


Теперь Java создаст файл только если его ещё нет.

Если файл уже существует, будет выброшено исключение:
FileAlreadyExistsException


Это удобно, когда нужно защититься от случайной перезаписи важных данных.

Например, можно явно обработать ситуацию:
try {
Files.writeString(path, json, StandardOpenOption.CREATE_NEW);
} catch (FileAlreadyExistsException e) {
throw new IllegalStateException("Export already exists", e);
}


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

👉 Java Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
7👍5🔥2
📂 Иерархия исключений в Java!

На картинке собрана структура Java exceptions: от базового Throwable до Exception, RuntimeException, IOException, Error и популярных наследников.

Например, NullPointerException, IllegalArgumentException, IndexOutOfBoundsException и ClassCastException относятся к RuntimeException.

Это unchecked-исключения: Java не заставляет явно ловить их через try-catch или прописывать в throws.

Сохрани, чтобы не путаться в checked, unchecked и Error!

👉 Java Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
9👍4🔥4
Проблема неправильного использования Optional в Java!

Optional часто используют как “защиту от null”, но если применять его везде подряд, код может стать сложнее, а не безопаснее.

Например, плохая практика - хранить Optional в поле класса:

public class User {
private Optional<String> email;
}


На первый взгляд кажется удобно: email может быть, а может не быть.

Но Optional задумывался в первую очередь как возвращаемое значение метода, а не как тип поля.

Лучше хранить само значение:

public class User {
private String email;
}


А Optional возвращать из метода, где отсутствие результата является нормальным сценарием:

public Optional<String> getEmail() {
return Optional.ofNullable(email);
}


Ещё один частый антипример принимать Optional как параметр метода:

public void updateEmail(Optional<String> email) {
}


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

Обычно понятнее сделать перегрузку метода или принять обычное nullable-значение с явной проверкой:

public void updateEmail(String email) {
if (email == null || email.isBlank()) {
throw new IllegalArgumentException("Email is blank");
}

this.email = email;
}


Также опасно вызывать get() без проверки:

User user = findUser(id).get();


Если пользователя нет, код упадёт с NoSuchElementException.

Безопаснее обработать отсутствие явно:

User user = findUser(id)
.orElseThrow(() -> new UserNotFoundException(id));


Или задать fallback:

String name = user.getName()
.orElse("Guest");


Optional хорошо подходит там, где метод может ничего не найти:

public Optional<User> findUser(Long id) {
return userRepository.findById(id);
}


Но если значение обязательно по бизнес-логике, лучше не прятать ошибку в Optional, а валидировать данные раньше.

👉 Java Ready | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
9👍5🔥4
This media is not supported in your browser
VIEW IN TELEGRAM
🤔 RavesliJava — обучение и основы Java для начинающих!

На сайте собран курс, который помогает освоить язык с нуля. Здесь разбираются основы синтаксиса, переменные, циклы, методы, массивы, ООП, классы и другие темы, необходимые для старта в Java-разработке. Материал подаётся последовательно и сопровождается примерами кода, благодаря чему обучение проходит проще и понятнее.

📌 Оставляю ссылочку: ravesli.com

👉 Java Ready | #сайт
Please open Telegram to view this post
VIEW IN TELEGRAM
👍84🔥2
Проблема “анемичных” запросов без валидации в Java!

В backend-коде часто создают DTO, которые просто переносят данные из API внутрь приложения.

Например:

public record CreateUserRequest(
String email,
String name
) {}


На первый взгляд всё нормально: есть email, есть имя.

Но если такой объект проходит дальше без проверки, в бизнес-логику могут попасть пустые строки, null, мусорные email и другие некорректные значения.

new CreateUserRequest("", " ");


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

Почему это опасно в реальных системах:
• ошибки появляются далеко от места ввода данных
• сервисы начинают дублировать одни и те же проверки
• в базе могут оказаться некорректные значения


Один из вариантов, это валидировать данные прямо на границе системы.

Например, через Bean Validation:

public record CreateUserRequest(
@Email String email,
@NotBlank String name
) {}


В Spring Boot такой объект можно проверить автоматически:

@PostMapping("/users")
public UserDto create(@Valid @RequestBody CreateUserRequest request) {
return userService.create(request);
}


Теперь некорректный запрос не пройдёт дальше контроллера.

Но важно помнить: API-валидация не заменяет доменную модель.

Если email важная часть бизнес-логики, лучше вынести его в отдельный value object:

public record Email(String value) {
public Email {
if (value == null || value.isBlank()) {
throw new IllegalArgumentException("Email is blank");
}
}
}


Тогда внутри приложения уже нельзя случайно создать пользователя с пустым email.

👉 Java Ready | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
10🔥4👍2
This media is not supported in your browser
VIEW IN TELEGRAM
❤️ Java Learning Roadmap — структурированное изучение Java!

Этот репозиторий хорошо подойдёт тем, кто хочет изучать Java без поиска информации. Здесь собрано много полезного материала для обучения: книги, roadmap’ы, практика, полезные репозитории, YouTube-каналы и материалы для подготовки к собеседованиям. Всё удобно разложено по разделам.

Оставляю ссылочку: GitHub 📱


👉 Java Ready | #репозиторий
Please open Telegram to view this post
VIEW IN TELEGRAM
10🔥5👍2
Знаете, что в Java можно запускать много блокирующих задач через virtual threads?

Раньше для параллельной обработки часто создавали пул обычных потоков:
ExecutorService executor = Executors.newFixedThreadPool(10);


Но если задачи в основном ждут сеть, базу данных, файлы или внешние API, обычные потоки могут быстро стать дорогими.

В Java 21 появились virtual threads:
ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor();


Теперь можно запускать отдельный лёгкий поток под каждую задачу:
executor.submit(() -> sendEmail(user));
executor.submit(() -> generateReport(user));
executor.submit(() -> syncAnalytics(user));


Это особенно удобно для I/O-heavy сценариев: HTTP-запросов, JDBC, чтения файлов, отправки уведомлений и интеграций с внешними сервисами.

Важно: virtual threads не делают CPU-heavy код быстрее сами по себе.

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

А вот для большого количества блокирующих операций virtual threads могут сильно упростить архитектуру.

👉 Java Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
6👍4🔥3
📂 Напоминалка по Hibernate и JPA!

Например, @OneToMany описывает связь между сущностями, а LAZY помогает не загружать лишние данные заранее.

На картинке — основные аннотации, стратегии выборки, кэширование и частые проблемы, которые важно помнить при работе с Hibernate и JPA.

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

👉 Java Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
👍112🔥2
Знаете, что в Java лучше работать с файлами через Path, а не собирать пути строками?

Иногда путь к файлу пишут так:
String path = "data/" + fileName;


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

В Java для этого есть Path:
Path path = Path.of("data", "users.json");


Java сама соберёт корректный путь для текущей системы.

С ним удобно работать через Files:
String json = Files.readString(path);


Или проверить, существует ли файл:
if (Files.exists(path)) {
// file exists
}


Можно безопасно получить вложенный путь:
Path avatar = Path.of("uploads")
.resolve(userId + ".png");


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

👉 Java Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
👍94🔥3
📂 Жизненный цикл потока в Java!

На картинке показаны основные состояния Thread: New, Runnable, Running, Blocked, Waiting, Time Waiting и Terminated.

Например, когда поток только создан через new Thread(...), он находится в состоянии New.

После вызова start() поток переходит в активную зону и может быть выбран планировщиком для выполнения.

Если поток ждёт освобождения lock, он попадает в Blocked.

Если поток ждёт сигнал от другого потока, например через wait() или join(), он переходит в Waiting.

А если ожидание ограничено по времени, например через sleep() или wait(timeout), это уже Timed Waiting.

Сохрани, чтобы быстрее понимать многопоточность в Java!

👉 Java Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
11👍2🔥2
📂 Напоминалка по Java 17 Sealed Classes!

Например, sealed class позволяет жёстко контролировать наследование, а permits явно указывает, какие классы могут расширять базовый тип.

На картинке — краткая шпаргалка по sealed, non-sealed и final классам, а также правилам построения закрытой иерархии в Java 17.

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

👉 Java Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
11🔥5👍3
Знаете, что в Java можно писать отрицательные проверки в Stream API без ! внутри lambda?

Часто код выглядит так:
.filter(name -> !name.isBlank())


Работает, но когда условий становится больше, такие отрицания начинают хуже читаться.

В Java есть Predicate.not():
.filter(Predicate.not(String::isBlank))


Так сразу видно: оставить все строки, которые не blank.

Например:
List<String> names = users.stream()
.map(User::name)
.filter(Objects::nonNull)
.filter(Predicate.not(String::isBlank))
.toList();


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

Особенно хорошо читается вместе с method reference:
Predicate.not(String::isEmpty)
Predicate.not(Collection::isEmpty)
Predicate.not(Optional::isEmpty)


Важно только не превращать это в головоломку: если условие сложное, лучше вынести его в отдельный метод с понятным названием.

Так код в stream-цепочках становится аккуратнее и легче читается.

👉 Java Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
10🔥4👍3
This media is not supported in your browser
VIEW IN TELEGRAM
👍 JavaNotes — всё самое важное по Java в одном месте!

Этот репозиторий представляет собой большой структурированный ресурс по Java, в котором собраны основные темы языка простым и понятным языком. Вместо просмотра десятков статей можно открыть один репозиторий и последовательно изучать материал.

Оставляю ссылочку: GitHub 📱


👉 Java Ready | #репозиторий
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥94👍2
Фильтруем список задач через Stream API в Java!

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

Создадим простой record:
record Task(String title, boolean done) {}


Теперь подготовим список:
List<Task> tasks = List.of(
new Task("Read docs", false),
new Task("Write tests", true),
new Task("Fix bug", false)
);


Можно пройтись циклом и вручную собрать новый список:
List<Task> active = new ArrayList<>();

for (Task task : tasks) {
if (!task.done()) {
active.add(task);
}
}


Но для такой задачи хорошо подходит Stream API:
List<Task> active = tasks.stream()
.filter(task -> !task.done())
.toList();


filter оставляет только элементы, которые проходят условие.

В нашем случае это задачи, у которых done() возвращает false.

Выведем результат:
active.forEach(System.out::println);


Получим только активные задачи:
Task[title=Read docs, done=false]
Task[title=Fix bug, done=false]


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

Например, можно выбрать только оплаченные заказы:
List<Order> paid = orders.stream()
.filter(Order::isPaid)
.toList();


filter это базовый, но очень полезный инструмент Stream API для отбора данных по условию.

👉 Java Ready | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
8👍3🔥3👎1