Java | Фишки и трюки
رفتن به کانال در Telegram
Java: примеры кода, интересные фишки и полезные трюки Купить рекламу: https://telega.in/c/java_tips_and_tricks ✍️По всем вопросам: @Pascal4eg Менеджер по рекламе: @shmyzna
نمایش بیشتر6 964
مشترکین
اطلاعاتی وجود ندارد24 ساعت
+557 روز
+2130 روز
آرشیو پست ها
6 964
⌨️ equals() и hashCode() - почему они ломают коллекции (и как это исправить)
Одна из самых коварных тем в Java — это контракт между
equals() и hashCode(). Ошибся и HashMap или HashSet начинают вести себя "магически" (читай: ломаются).
📦 Проблема на практике
Set<User> users = new HashSet<>();
users.add(new User("Alex"));
System.out.println(users.contains(new User("Alex"))); // ❌ false
🤨 Почему false, если значения одинаковые?
⚠️ Причина
По умолчанию equals() сравнивает ссылки (==), а не содержимое.
✅ Правильная реализация
public class User {
private String name;
// equals
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof User)) return false;
User user = (User) o;
return Objects.equals(name, user.name);
}
// hashCode
@Override
public int hashCode() {
return Objects.hash(name);
}
}
🔥 Почему важны ОБА метода?
Если переопределить только equals():
users.add(new User("Alex"));
users.contains(new User("Alex")); // ❌ всё ещё может быть false
👉 Потому что HashSet сначала смотрит на hashCode(), а потом уже на equals().
⚡ Контракт, который нельзя нарушать
1. Если equals() возвращает true → hashCode() обязан быть одинаковым
2. Если hashCode() одинаковый → equals() может быть как true, так и false
💣 Классическая ошибка
Изменяем объект после добавления в HashSet:
User user = new User("Alex");
users.add(user);
user.setName("Bob");
users.contains(user); // ❌ может вернуть false
👉 Объект "потерялся" в коллекции
🧠 Как избежать проблем
* Делай объекты immutable (final поля)
* Используй record (Java 16+):
public record User(String name) {}
👉 equals() и hashCode() генерируются автоматически и корректно
📌 Вывод
Коллекции в Java работают быстро благодаря hashCode(),
но требуют строгого соблюдения контракта.
Нарушишь - получишь баги, которые очень сложно отловить 🐛6 964
На собес в Сбер — 60 минут, live-coding и SQL прямо на камеру.
Знаешь, что спросят?
Мы знаем. И выложили.
@Java Jub — Java-вакансии + реальные вопросы, задачи и стек к каждой.
📱 Переходи: Java Jub (Job)
6 964
⌨️ Ленивая инициализация через `Supplier` - мощнее, чем кажется
В Java есть недооценённая фишка - ленивые вычисления через
Supplier. Это может сильно упростить код и улучшить производительность.
📦 Что такое `Supplier`?
Это функциональный интерфейс из java.util.function, который просто возвращает значение:
Supplier<String> supplier = () -> "Hello";
System.out.println(supplier.get());
Но магия начинается, когда используешь его правильно 👇
🔥 Кейс: дорогое вычисление
public String getData() {
System.out.println("Loading...");
return "data";
}
Теперь сравни:
❌ Обычный вызов:
String result = getData(); // всегда выполняется
✅ Ленивый вызов:
Supplier<String> supplier = this::getData;
// вызов произойдёт только здесь
String result = supplier.get();
👉 Код выполняется только когда реально нужен результат.
⚡ Практическое применение: логирование
logger.debug("Result: " + expensiveOperation());
❗ Даже если debug выключен — expensiveOperation() всё равно выполнится.
✅ Правильно:
logger.debug(() -> "Result: " + expensiveOperation());
👉 Вычисление произойдёт только если лог реально пишется.
🧠 Комбинация с `Optional`
String name = Optional.ofNullable(getName())
.orElseGet(() -> generateDefaultName());
👉 generateDefaultName() вызовется только если значение отсутствует
(в отличие от orElse, который выполняется всегда)
🚀 Паттерн: кэширование (lazy cache)
Supplier<String> cached = new Supplier<>() {
private String value;
@Override
public String get() {
if (value == null) {
value = loadExpensiveData();
}
return value;
}
};
👉 Получаешь простую ленивую инициализацию без лишних библиотек
📌 Вывод
Supplier — это не просто "лямбда ради лямбды", а инструмент для:
* ленивых вычислений
* оптимизации
* более чистого API6 964
Играй и выигрывай промокоды на 20 000 рублей!
Тот момент, когда в игре ❤️❤️❤️ закончились, а ответ на вопрос не знаешь!
Точно нужна помощь друзей, родных, девочек, Вани и Аннушки вместе взятых! Тем более, когда на кону промокоды по 20 000 рублей на покупки в Спортмастере...
Ждем тебя:
Переходи в бота, следуй инструкциям и запускай игру
Создавай своего персонажа и выбирай, на чем он будет гонять
Управляй наклоном телефона и докажи, кто здесь главный гонщик
Топ-10 лучших игроков получат промокоды по 20 000 рублей, чтобы экипироваться к новому сезону на колёсах.
Играем до 30 апреля, погнали!
Перейти на сайт
#реклама 16+
О рекламодателе
6 964
🌱 Spring Cloud Config — это проект в экосистеме Spring, который предоставляет сервер и клиент для централизованного управления конфигурацией в распределённых системах. Основная идея Spring Cloud Config — это вынесение конфигурационных файлов из приложений в единое место (например, репозиторий Git), чтобы облегчить управление конфигурацией для различных сервисов в микросервисной архитектуре.
Основные компоненты
✔️ Config Server — сервер, который хранит конфигурации (обычно в Git) и раздает их микросервисам.
✔️ Config Client — клиент в микросервисах, который получает конфигурации от Config Server.
Возможности
✔️ Централизация конфигураций всех сервисов.
✔️ Поддержка версионирования конфигураций (например, через Git).
✔️ Динамическое обновление конфигураций без перезапуска приложений с помощью Spring Cloud Bus.
✔️ Поддержка различных сред и профилей (dev, prod и т.д.).
Пример настройки Config Server:
spring:
cloud:
config:
server:
git:
uri: https://github.com/your-repo/config-repo
Пример настройки Config Client:
spring:
cloud:
config:
uri: http://localhost:8888
profile: dev
Преимущества: упрощает управление конфигурациями, поддерживает разные среды, позволяет динамически обновлять настройки.
Недостатки: важен контроль за доступом и стабильностью Config Server.
#java #Spring #Cloud #Config6 964
🔴 Завтра тестовое собеседование с Java-разработчиком
15 апреля(уже завтра!) в 19:00 по мск приходи онлайн на открытое собеседование, чтобы посмотреть на настоящее интервью на Middle Java-разработчика.
Как это будет:
📂 Виктор Анохин, старший разработчик из WildBerries, будет задавать реальные вопросы и задачи разработчику-добровольцу
📂 Виктор будет комментировать каждый ответ респондента, чтобы дать понять чего от вас ожидает собеседующий на интервью
📂 В конце можно будет задать любой вопрос Виктору
Это бесплатно. Эфир проходит в рамках менторской программы от ШОРТКАТ для Java-разработчиков, которые хотят повысить свой грейд, ЗП и прокачать скиллы.
Переходи в нашего бота, чтобы получить ссылку на эфир → @shortcut_sh_bot
Реклама.
О рекламодателе.
6 964
🔗 В чем разница между
== и .equals()?
При сравнении объектов в Java важно понимать различие между == и .equals().
✔️ == сравнивает ссылки на объекты, проверяя, указывают ли они на одну и ту же область памяти.
✔️ .equals() используется для сравнения содержимого объектов, если метод переопределен.
Пример:
String a = new String("Java");
String b = new String("Java");
System.out.println(a == b); // false (разные ссылки)
System.out.println(a.equals(b)); // true (сравнение содержимого)
💡 Совет: для корректного сравнения объектов всегда переопределяйте метод equals() в вашем классе.
#java #equals #comparison6 964
В России можно посещать IT-мероприятия хоть каждый день: как оффлайн, так и онлайн
Но где их находить? Как узнавать о них раньше, чем когда все начнут выкладывать фотографии оттуда?
Переходите на канал IT-Мероприятия России. В нём каждый день анонсируются мероприятия со всех городов России
📆 в канале размещаются как онлайн, так и оффлайн мероприятия;
👩💻 можно найти ивенты по любому стеку: программирование, frontend-backend разработка, кибербезопасность, дата-аналитика, osint, devops и другие;
🎙 разнообразные форматы мероприятий: митапы с коллегами по цеху, конференции и вебинары с известными опытными специалистами, форумы и олимпиады от важных представителей индустрии и многое другое
А чтобы не искать по разным форумам и чатам новости о предстоящих ивентах:
🚀 IT-мероприятия России — подписывайся и будь в курсе всех предстоящих мероприятий!
6 964
🖥 Блоки инициализации в Java
Блоки инициализации позволяют гибко управлять созданием объектов. Вот как их правильно использовать:
💠 Нестатические блоки
Выполняются перед конструктором:
public class Logger {
private String prefix;
{ // Блок инициализации экземпляра (выполняется перед конструктором)
prefix = "[LOG] " + LocalDateTime.now(); // Инициализация префикса с текущей датой/временем
System.out.println("Логгер готов!"); // Сообщение о готовности логгера
}
public Logger() {
System.out.println(prefix + " | Новый объект"); // Вывод информации о создании объекта
}
}
▸ Для чего: предварительная настройка полей, валидация, логирование.
💠 Статические блоки
Срабатывают один раз при загрузке класса:
public class ConfigLoader {
static {
System.out.println("Загружаем конфиги...");
// Здесь можно читать файлы, подключать БД и т.д.
}
}
▸ Для чего: инициализация кэшей, регистрация драйверов, загрузка ресурсов.
📝 Когда что использовать
- Нестатические блоки → простая инициализация полей
- Статические блоки → настройка системных ресурсов
🧬Дополнение:
Для улучшения читаемости кода используйте блоки инициализации для простых операций. Избегайте сложной логики — это может затруднить отладку и понимание приложения.6 964
0% налогов и легальный Stripe для IT
Ищете надежную базу для масштабирования IT-компании? Откройте бэк-офис в ведущем IT-хабе Центральной Азии.
Статус резидента IT Park дает четкие преимущества:
0% налогов: полное освобождение от налога на прибыль, социалку и НДС (экспорт).
7.5% НДФЛ: минимальная ставка для ваших сотрудников.
Финтех-интеграция: легальная работа со Stripe, PayPal и мировыми банками.
Скорость: регистрация юрлица и получение статуса удаленно за 10 дней.
Более 1000 международных компаний уже ведут глобальный бизнес через Узбекистан.
Оставьте заявку и получите бесплатную консультацию:
Получить консультацию
#реклама
outsource.gov.uz
О рекламодателе
6 964
⌨️ Срезы в стримах. Метод takeWhile
В Java 9 появилось два новых метода, полезных для выбора элементов потока с хорошей производительностью: takeWhile и dropWhile.
Допустим, у нас есть следующий список блюд:
List<Dish> specialMenu = Arrays.asList(
new Dish("seasonal fruit", 120),
new Dish("prawns", 300),
new Dish("rice", 350),
new Dish("chicken", 400),
new Dish("french fries", 530));
Для получения блюд с калорийностью меньше 320, можно воспользоваться операцией filter. Недостаток операции filter в том, что она требует прохода в цикле по всему потоку данных с применением предиката ко всем элементам.
В нашем примере список уже отсортирован по числу калорий. Вместо того, чтобы пройтись по каждому элементу, можно прекратить работу сразу же после обнаружения блюда, содержащего 320 калорий или более. В случае небольшого списка это может показаться не таким уж громадным преимуществом, но при работе с потенциально большим потоком элементов окажется весьма полезным.
Поможет нам в этом операция takeWhile! Она позволяет выполнить срез любого потока данных (даже бесконечного) с помощью предиката. И, к счастью, она прекращает работу сразу же по обнаружении неподходящего элемента. Вот как ее следует использовать:
List<Dish> sliceMenu1
= specialMenu.stream()
.takeWhile(dish -> dish.getCalories() < 320)
.collect(toList());
#java #stream #takeWhile6 964
🚗 Готовишься к экзамену в ГИБДД?
Попробуй удобное Android-приложение для изучения ПДД и решения билетов:
👉 https://play.google.com/store/apps/details?id=com.pascal4eg.pdd
Что внутри:
✔️ Актуальные правила и штрафы
✔️ Новые экзаменационные билеты
✔️ Режим экзамена — как в ГИБДД
✔️ Лёгкое приложение — всего 30 МБ
🌙 Тёмная тема для комфортного обучения
Готовься к экзамену быстро и без лишнего стресса!
6 964
⌨️ Какими значениями инициализируются переменные по умолчанию?
byte — (byte)0;
short — (short)0;
int — 0;
long — 0L;
float — 0f;
double — 0d;
char — \u0000;
boolean — false;
Объекты (в том числе String) — null.
#java #initialization6 964
⌨️ Чтение и запись файла с помощью класса
Files
Чтение всего файла в список строк (readAllLines)
import java.nio.file.*;
import java.io.IOException;
import java.util.List;
public class Main {
public static void main(String[] args) throws IOException {
Path path = Paths.get("example.txt");
List<String> lines = Files.readAllLines(path);
lines.forEach(System.out::println);
}
}
📌 Читает весь файл в List<String>, удобно для небольших файлов.
Запись в файл (write)
List<String> lines = List.of("Первая строка", "Вторая строка");
Files.write(Paths.get("output.txt"), lines);
📌 Если файла нет — создаст, если есть — перезапишет.
Добавление в файл (без перезаписи):
Files.write(Paths.get("output.txt"), lines, StandardOpenOption.APPEND);
#java #Files #readAllLines #write6 964
🔴 Завтра тестовое собеседование с Java-разработчиком
1 апреля(уже завтра!) в 19:00 по мск приходи онлайн на открытое собеседование, чтобы посмотреть на настоящее интервью на Middle Java-разработчика.
Как это будет:
📂 Виктор Анохин, старший разработчик из WildBerries, будет задавать реальные вопросы и задачи разработчику-добровольцу
📂 Виктор будет комментировать каждый ответ респондента, чтобы дать понять чего от вас ожидает собеседующий на интервью
📂 В конце можно будет задать любой вопрос Виктору
Это бесплатно. Эфир проходит в рамках менторской программы от ШОРТКАТ для Java-разработчиков, которые хотят повысить свой грейд, ЗП и прокачать скиллы.
Переходи в нашего бота, чтобы получить ссылку на эфир → @shortcut_sh_bot
Реклама.
О рекламодателе.
6 964
⌨️ JVM Escape Analysis: Миф о том, что все объекты живут в Куче (Heap)
Вспомните свои первые уроки по Java. Нам всем говорили: "Примитивы (
int, double) живут в быстром Стеке (Stack), а вот объекты (new Object()) всегда создаются в медленной Куче (Heap), и потом за ними приходит Garbage Collector".
Спойлер: В некоторых случаях JVM может вообще не создавать объект в heap
Создание объекта в Heap не бесплатно. Нужно выделить память, синхронизировать потоки, а потом еще и напрягать GC, чтобы этот мусор собрать. Поэтому JIT-компилятор научился магии под названием Escape Analysis (Анализ утечки).
Как это работает?
Допустим, у вас есть метод:
public int calculateArea(int x, int y) {
// Создаем временный объект
Point p = new Point(x, y);
return p.getX() * p.getY();
}
Казалось бы, при каждом вызове метода мы засоряем Heap новым объектом Point. Но JIT-компилятор во время работы программы анализирует код и задает себе вопрос: "А убегает ли этот объект за пределы метода?"
В нашем случае p никуда не передается, не сохраняется в глобальную коллекцию и не возвращается наружу (возвращается только int). Объект не убегает (No Escape).
✨ Магия Скалярной замены (Scalar Replacement)
Поняв это, JVM принимает гениальное решение: она вообще не создает объект Point в Куче!
Вместо этого она "расщепляет" объект на его составляющие примитивы (поля x и y) и держит их в регистрах или других внутренних структурах JIT.
Для процессора этот код превращается во что-то такое:
public int calculateArea(int x, int y) {
int p_x = x;
int p_y = y;
return p_x * p_y;
}
Что это дает?
1. 0 байт выделено в Heap.
2. 0 миллисекунд потрачено на работу Garbage Collector.
3. Скорость выполнения может быть очень близка к нативной производительности.
Итог:
В большинстве обычных случаев можно не бояться создавать короткоживущие объекты внутри методов (DTO, обертки, Optional), если это делает код чище. JVM достаточно умна, чтобы "схлопнуть" их и не нагружать память. Экономить на спичках и переиспользовать один объект через reset() больше не нужно.6 964
⌨️ Что такое static метод интерфейса?
Статические методы интерфейса похожи на методы по умолчанию, за исключением того, что для них отсутствует возможность переопределения в классах, реализующих интерфейс.
✔️Статические методы в интерфейсе являются частью интерфейса без возможности переопределить их для объектов класса реализации;
✔️Методы класса
java.lang.Object нельзя переопределить как статические;
✔️Статические методы в интерфейсе используются для обеспечения вспомогательных методов, например, проверки на null, сортировки коллекций и т.д.
Вызывать static метод интерфейса можно используя имя интерфейса:
interface Paper {
static void show() {
System.out.println("static show()");
}
}
class Licence {
public void showPaper() {
Paper.show();
}
}6 964
🔍 5 фишек
Stream API, которые упростят код
Stream API – мощный инструмент, но в нём есть интересные методы, о которых многие забывают.
🟢takeWhile() – берёт элементы, пока условие true.
🟢dropWhile() – пропускает элементы, пока условие true.
🟢iterate() – создаёт бесконечный поток.
🟢flatMap() – преобразует вложенные структуры в плоский поток.
🟢collect(Collectors.toMap()) – собирает Stream в Map.
✔️ Пример:
List<Integer> numbers = List.of(1, 2, 3, 4, 5);
numbers.stream()
.takeWhile(n -> n < 4)
.forEach(System.out::println); // 1, 2, 3
💡 Совет: Используйте эти методы, чтобы писать более лаконичный код без лишних for.
#java #streamapi #functionalprogramming6 964
⌨️ Дайте определение понятию «интерфейс». Какие модификаторы по умолчанию имеют поля и методы интерфейсов?
Ключевое слово
interface используется для создания полностью абстрактных классов. Основное предназначение интерфейса - определять каким образом мы можем использовать класс, который его реализует. Создатель интерфейса определяет имена методов, списки аргументов и типы возвращаемых значений, но не реализует их поведение. Все методы неявно объявляются как public.
Начиная с Java 8 в интерфейсах разрешается размещать реализацию методов по умолчанию default и статических static методов.
Интерфейс также может содержать и поля. В этом случае они автоматически являются публичными public, статическими static и неизменяемыми final.6 964
JVM-инженеры, общий сбор: 28 марта Яндекс проведет Я.Субботник по JVM-языкам
Это митап для разработчиков, которые работают с языками Java Virtual Machine. Встреча пройдет в московском офисе Яндекса и в онлайн. Будем обсуждать новые подходы, делиться практическим опытом и нетворкать в неформальной обстановке.
В программе — доклады про ускорение Java-фреймворков на примере Quarkus, устройство трассирующего профайлера (Qubership Profiler), реальные подводные камни java.time и оптимизация GraphQL API на базе GraphQL Java и Spring Framework. А еще круглые столы, активность от Яндекс Вертикалей и афтерпати.
Подать заявку на митап можно здесь.
اکنون در دسترس! پژوهش تلگرام ۲۰۲۵ — مهمترین بینشهای سال 
