Что выведет код?
#Tasks
import java.util.Optional;
public class Task180625 {
public static void main(String[] args) {
Optional<String> opt = Optional.ofNullable(null)
.flatMap(s -> Optional.of("value"))
.or(() -> Optional.of("default"));
System.out.println(opt.get());
}
}
#Tasks
Что такое try-with-resources? 🤓
Ответ:
try-with-resources (Java 7+) автоматически закрывает ресурсы, реализующие интерфейс AutoCloseable (например, FileInputStream). Это упрощает управление ресурсами, предотвращая утечки.
Пример:
try (FileInputStream fis = new FileInputStream("file.txt")) {
// Работа с файлом
} catch (IOException e) {
e.printStackTrace();
}
Ресурсы закрываются автоматически после выхода из блока try.
#собеседование
Ответ:
Пример:
try (FileInputStream fis = new FileInputStream("file.txt")) {
// Работа с файлом
} catch (IOException e) {
e.printStackTrace();
}
Ресурсы закрываются автоматически после выхода из блока try.
#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
Ссылочные типы в Java — var
Ключевое слово var, добавленное в Java 10, представляет собой локальную типизированную переменную с выводом типа (local variable type inference). Хотя var сам по себе не является типом (в отличие от String, List, и т.п.), он оперирует ссылочными (и примитивными) типами — именно поэтому мы рассматриваем его как часть экосистемы ссылочных типов.
var позволяет сократить синтаксис, делая код лаконичнее, при этом тип переменной всё равно строго определяется на этапе компиляции.
Синтаксис и пример использования
Это полностью эквивалентно:
Тип переменной вычисляется во время компиляции, и далее не может быть изменён. var нельзя использовать без инициализации:
Что происходит на уровне компиляции и памяти
На уровне байткода и JVM var не существует — это просто синтаксический сахар. Компилятор javac анализирует выражение справа от знака =, определяет точный тип и подставляет его вместо var.
Пример:
Компилируется в:
На уровне памяти всё ведёт себя так же, как если бы вы явно указали тип: объект User создаётся в куче (heap), а ссылка user — в стеке (если переменная локальная). То есть var никак не влияет на runtime-поведение, управление памятью или структуру объектов.
Где можно использовать var
Только внутри методов (локальные переменные)
В циклах for-each
В try-with-resources
Примеры:
Нельзя использовать:
Для параметров методов
Для полей классов
В сигнатурах методов
Преимущества использования var
1. Ускорение читаемости
→
Меньше дублирования, особенно при использовании дженериков.
2. Быстрая прототипизация
При тестировании и прототипах позволяет писать код быстрее.
3. Минимизация шаблонного кода
Особенно полезно в циклах:
Недостатки и подводные камни
1. Потеря явности
var может скрыть реальный тип переменной, что ухудшает читаемость, особенно в больших проектах или при чтении чужого кода:
2. Не подходит для API и контрактов
Вы не можете использовать var в методах, полях и интерфейсах, что делает его локальной удобной вещью, но не универсальным инструментом проектирования.
3. Опасности с null
Пример:
Тип должен быть определён по выражению. null без контекста не имеет типа.
4. Может скрыть ошибки
В случае приведения типов или неочевидных фабрик:
Программист может подумать, что это ArrayList.
5. Не подходит для примитивов, если важна производительность
Лучшие практики использования var
Использовать var, когда тип очевиден из правой части.
Не использовать в публичных API и библиотечном коде.
Избегать var, если тип сложный или поведение неочевидно.
Можно комбинировать с IDE: использовать var в коде, но просматривать тип через наведение мыши.
Пример хорошего использования:
Пример плохого использования:
#Java #для_новичков #beginner #reference_types #var
Ключевое слово var, добавленное в Java 10, представляет собой локальную типизированную переменную с выводом типа (local variable type inference). Хотя var сам по себе не является типом (в отличие от String, List, и т.п.), он оперирует ссылочными (и примитивными) типами — именно поэтому мы рассматриваем его как часть экосистемы ссылочных типов.
var позволяет сократить синтаксис, делая код лаконичнее, при этом тип переменной всё равно строго определяется на этапе компиляции.
Синтаксис и пример использования
var list = new ArrayList<String>();
var name = "John";
var age = 25;
Это полностью эквивалентно:
ArrayList<String> list = new ArrayList<>();
String name = "John";
int age = 25;
Тип переменной вычисляется во время компиляции, и далее не может быть изменён. var нельзя использовать без инициализации:
var name; // ошибка компиляции
Что происходит на уровне компиляции и памяти
На уровне байткода и JVM var не существует — это просто синтаксический сахар. Компилятор javac анализирует выражение справа от знака =, определяет точный тип и подставляет его вместо var.
Пример:
var user = new User("Alice");
Компилируется в:
User user = new User("Alice");
На уровне памяти всё ведёт себя так же, как если бы вы явно указали тип: объект User создаётся в куче (heap), а ссылка user — в стеке (если переменная локальная). То есть var никак не влияет на runtime-поведение, управление памятью или структуру объектов.
Где можно использовать var
Только внутри методов (локальные переменные)
В циклах for-each
В try-with-resources
Примеры:
for (var entry : map.entrySet()) {
...
}
try (var stream = Files.lines(path)) {
...
}
Нельзя использовать:
Для параметров методов
Для полей классов
В сигнатурах методов
Преимущества использования var
1. Ускорение читаемости
Map<String, List<User>> usersByRole = new HashMap<>();
→
var usersByRole = new HashMap<String, List<User>>();
Меньше дублирования, особенно при использовании дженериков.
2. Быстрая прототипизация
При тестировании и прототипах позволяет писать код быстрее.
3. Минимизация шаблонного кода
Особенно полезно в циклах:
for (var entry : map.entrySet()) { ... }
Недостатки и подводные камни
1. Потеря явности
var может скрыть реальный тип переменной, что ухудшает читаемость, особенно в больших проектах или при чтении чужого кода:
var x = process(); // Что возвращает process()? Map? List? String?
2. Не подходит для API и контрактов
Вы не можете использовать var в методах, полях и интерфейсах, что делает его локальной удобной вещью, но не универсальным инструментом проектирования.
3. Опасности с null
Пример:
var data = null; // ошибка компиляции: невозможно вывести тип
Тип должен быть определён по выражению. null без контекста не имеет типа.
4. Может скрыть ошибки
В случае приведения типов или неочевидных фабрик:
var list = Arrays.asList(1, 2, 3); // list: List<Integer>, но неизменяемый!
Программист может подумать, что это ArrayList.
5. Не подходит для примитивов, если важна производительность
var x = 42; // int
var y = 42L; // long
// Может быть неожиданным, если x и y пойдут в разные ветви перегрузки
Лучшие практики использования var
Использовать var, когда тип очевиден из правой части.
Не использовать в публичных API и библиотечном коде.
Избегать var, если тип сложный или поведение неочевидно.
Можно комбинировать с IDE: использовать var в коде, но просматривать тип через наведение мыши.
Пример хорошего использования:
var list = new ArrayList<String>(); // тип легко читается
Пример плохого использования:
var result = service.process(); // неясно, что такое result
#Java #для_новичков #beginner #reference_types #var
Что выведет код?
#Tasks
import java.util.function.Function;
public class Task190625 {
public static void main(String[] args) {
var x = (Function<Function<Integer, Integer>, Integer>)
f -> f.apply(10);
var y = x.apply(n -> n * 2);
System.out.println(y);
}
}
#Tasks
StreamAPI JAVA.
Великолепие минимализма
Видео посвященное изучению Stream API в Java.
Что мы узнали:
⏺ Что такое Stream API и зачем оно вообще нужно.
⏺ Что такое Императивный и Декларативный подходы.
⏺ Рассмотрели функциональные интерфейсы и их основные виды.
⏺ Рассмотрели основные функциональные промежуточные и терминальные методы.
⏺ Посмотрели все это на примерах.
Если хотите посмотреть с более подробными примерами и описанием:
GitHub - https://github.com/Oleborn/StreamAPI_Research
(понравилось - поставь звездочку)
Ссылка на Youtube
Ссылка на Рутьюб
Смотрите, ставьте лайки, подписывайтесь на каналы!
Великолепие минимализма
Видео посвященное изучению Stream API в Java.
Что мы узнали:
Если хотите посмотреть с более подробными примерами и описанием:
GitHub - https://github.com/Oleborn/StreamAPI_Research
Ссылка на Youtube
Ссылка на Рутьюб
Смотрите, ставьте лайки, подписывайтесь на каналы!
Please open Telegram to view this post
VIEW IN TELEGRAM
Что такое Error в Java и чем он отличается от Exception? 🤓
Ответ:
Error и Exception — наследники Throwable.
Error обозначает серьезные системные ошибки, которые обычно нельзя обработать (например, OutOfMemoryError).
Exception — это ошибки, которые можно и нужно обрабатывать (например, IOException).
Программист редко обрабатывает Error, но должен учитывать Exception.
#собеседование
Ответ:
Error обозначает серьезные системные ошибки, которые обычно нельзя обработать (например, OutOfMemoryError).
Exception — это ошибки, которые можно и нужно обрабатывать (например, IOException).
Программист редко обрабатывает Error, но должен учитывать Exception.
#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
Best Practices и расширенные сценарии работы с Flyway
1. Организация миграций
1.1. Разделение миграций по окружениям
Проблема:
Разные БД для dev/test/prod могут требовать специфичных скриптов (например, тестовые данные только для dev).
Решение:
Структура папок:
Настройка application.yml для dev:
1.2. Работа с существующей БД (baseline)
Проблема:
Flyway ожидает пустую БД или таблицу flyway_schema_history. Если БД уже используется, требуется инициализация.
Решение:
Включить baseline-on-migrate:
Вручную через CLI:
Важно:
После baseline миграции с версией ≤ baselineVersion игнорируются.
2. Тестирование миграций
2.1. Интеграция с Testcontainers + JUnit
Цель:
Проверить, что миграции применяются без ошибок в изолированной БД.
Пример теста (Java + JUnit 5):
Что проверяем:
Применение всех миграций без исключений.
Соответствие схемы ожиданиям (можно добавить проверку через DataSource).
3. Работа в команде
3.1. Именование файлов
Правила:
Уникальность версий:
Используйте дату + порядковый номер: V20240315-1__Add_users_table.sql.
Описательные имена:
Плохо: V1__Changes.sql.
Хорошо: V20240315-2__Alter_users_add_email.sql.
3.2. Запрет изменения примененных скриптов
Проблема:
Изменение уже выполненного скрипта приводит к ошибке:
Решение:
Никогда не изменять содержимое V*-файлов после их применения.
Для исправлений:
Создать новую миграцию с корректировкой:
Если критично, использовать flyway repair (пересчитывает контрольные суммы).
Исключение:
R__-миграции (повторяемые) можно изменять — они переприменяются при изменениях.
4. Расширенные сценарии
4.1. Миграции для нескольких схем БД
Настройка:
4.2. Шаблонизация SQL
Проблема:
Разные SQL-синтаксисы для PostgreSQL/Oracle.
Решение (через Maven/Gradle):
Используйте placeholders в pom.xml:
В SQL:
4.3. Откаты (безопасная альтернатива)
Тактика:
Для деструктивных изменений (DROP, DELETE) создавать "обратные" миграции:
#Java #middle #Flyway
1. Организация миграций
1.1. Разделение миграций по окружениям
Проблема:
Разные БД для dev/test/prod могут требовать специфичных скриптов (например, тестовые данные только для dev).
Решение:
Структура папок:
db/
migration/
dev/
V1__Dev_only_data.sql
prod/
V1__Prod_indexes.sql
common/
V1__Base_schema.sql
Настройка application.yml для dev:
spring:
flyway:
locations: classpath:db/migration/common, classpath:db/migration/dev
1.2. Работа с существующей БД (baseline)
Проблема:
Flyway ожидает пустую БД или таблицу flyway_schema_history. Если БД уже используется, требуется инициализация.
Решение:
Включить baseline-on-migrate:
spring:
flyway:
baseline-on-migrate: true
baseline-version: 1.0 # Версия, с которой начнется контроль
Вручную через CLI:
flyway baseline -baselineVersion="1.0"
Важно:
После baseline миграции с версией ≤ baselineVersion игнорируются.
2. Тестирование миграций
2.1. Интеграция с Testcontainers + JUnit
Цель:
Проверить, что миграции применяются без ошибок в изолированной БД.
Пример теста (Java + JUnit 5):
import org.flywaydb.core.Flyway;
import org.junit.jupiter.api.Test;
import org.testcontainers.containers.PostgreSQLContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
@Testcontainers
public class FlywayMigrationTest {
@Container
private static final PostgreSQLContainer<?> postgres =
new PostgreSQLContainer<>("postgres:15");
@Test
void testMigrations() {
Flyway flyway = Flyway.configure()
.dataSource(
postgres.getJdbcUrl(),
postgres.getUsername(),
postgres.getPassword()
)
.load();
flyway.migrate(); // Упадет, если есть ошибки
}
}
Что проверяем:
Применение всех миграций без исключений.
Соответствие схемы ожиданиям (можно добавить проверку через DataSource).
3. Работа в команде
3.1. Именование файлов
Правила:
Уникальность версий:
Используйте дату + порядковый номер: V20240315-1__Add_users_table.sql.
Описательные имена:
Плохо: V1__Changes.sql.
Хорошо: V20240315-2__Alter_users_add_email.sql.
3.2. Запрет изменения примененных скриптов
Проблема:
Изменение уже выполненного скрипта приводит к ошибке:
Validate failed: Migration checksum mismatch for V1__Create_table.sql
Решение:
Никогда не изменять содержимое V*-файлов после их применения.
Для исправлений:
Создать новую миграцию с корректировкой:
-- V20240315-3__Fix_users_table.sql
ALTER TABLE users ALTER COLUMN email SET NOT NULL;
Если критично, использовать flyway repair (пересчитывает контрольные суммы).
Исключение:
R__-миграции (повторяемые) можно изменять — они переприменяются при изменениях.
4. Расширенные сценарии
4.1. Миграции для нескольких схем БД
Настройка:
spring:
flyway:
schemas: public, audit
default-schema: public
В SQL-файлах укажите схему явно:
sql
-- V1__Create_audit_table.sql
CREATE TABLE audit.logs (
id SERIAL PRIMARY KEY,
message TEXT
);
4.2. Шаблонизация SQL
Проблема:
Разные SQL-синтаксисы для PostgreSQL/Oracle.
Решение (через Maven/Gradle):
Используйте placeholders в pom.xml:
<configuration>
<placeholders>
<table.prefix>${env}</table.prefix>
</placeholders>
</configuration>
В SQL:
CREATE TABLE ${table.prefix}_users (...);
4.3. Откаты (безопасная альтернатива)
Тактика:
Для деструктивных изменений (DROP, DELETE) создавать "обратные" миграции:
-- V5__Drop_users.sql
DROP TABLE users;
-- V6__Restore_users.sql (если нужно откатить)
CREATE TABLE users (...); -- Повторяем структуру из V1
INSERT INTO users (...) SELECT ... FROM backup_users;
Использовать резервные копии перед рискованными операциями.
#Java #middle #Flyway
Что выведет код?
#Tasks
import java.util.function.Supplier;
public class Task200625 {
public static void main(String[] args) {
Supplier<Integer> supplier = () -> {
System.out.print("A");
return 1;
};
System.out.print("B");
supplier.get();
System.out.print("C");
}
}
#Tasks
Продолжаем выбирать темы для разбора и голосовать за рассмотрение предложенных! 🤓
Голосуем за тему к рассмотрению в эти выходные!
Выбираем новую тему!
(можете предложить что-то из того, что предлагали на прошлой и позапрошлых неделях и что проиграло в голосовании!)
Не стесняемся!✌️
Голосуем за тему к рассмотрению в эти выходные!
Выбираем новую тему!
(можете предложить что-то из того, что предлагали на прошлой и позапрошлых неделях и что проиграло в голосовании!)
Не стесняемся!
Please open Telegram to view this post
VIEW IN TELEGRAM
Что такое Thread.sleep() и чем он отличается от Thread.yield()? 🤓
Ответ:
Thread.sleep(long millis) приостанавливает выполнение текущего потока на указанное время (в миллисекундах), не освобождая монитор. Может выбросить InterruptedException.
Thread.yield() дает возможность другим потокам с таким же приоритетом выполниться, но не гарантирует переключение.
Пример:
Thread.sleep(1000); // Пауза на 1 секунду
Thread.yield(); // Уступить процессор другим потокам
#собеседование
Ответ:
Thread.yield() дает возможность другим потокам с таким же приоритетом выполниться, но не гарантирует переключение.
Пример:
Thread.sleep(1000); // Пауза на 1 секунду
Thread.yield(); // Уступить процессор другим потокам
#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM