Java for Beginner
743 subscribers
727 photos
205 videos
12 files
1.19K links
Канал от новичков для новичков!
Изучайте Java вместе с нами!
Здесь мы обмениваемся опытом и постоянно изучаем что-то новое!

Наш YouTube канал - https://www.youtube.com/@Java_Beginner-Dev

Наш канал на RUTube - https://rutube.ru/channel/37896292/
Download Telegram
Сколько языков программирования вы знаете?
Anonymous Poll
50%
Пока ни одного) Java бы выучить!
15%
Java!
19%
2
15%
3 и больше
👍1
Реактивное программирование

R2DBC vs JDBC: реактивные базы данных


Исторический контекст: что такое JDBC и почему он доминировал десятилетиями

JDBC — это стандартный API Java для доступа к реляционным базам данных, появившийся ещё в JDK 1.1 (1997 год).

Он позволяет выполнять SQL-запросы, управлять соединениями и обрабатывать результаты через унифицированный интерфейс, независимо от конкретной БД (PostgreSQL, MySQL, Oracle и т.д.).


Ключевые компоненты JDBC:
DriverManager или DataSource: Для получения соединения (Connection).
Statement/PreparedStatement: Для выполнения SQL (executeQuery, executeUpdate).
ResultSet: Для чтения результатов (next(), getString() и т.д.).
Transaction management: commit(), rollback().


Пример простого JDBC-кода:
import java.sql.*;
public class JdbcExample {
public static void main(String[] args) {
try (Connection conn = DriverManager.getConnection("jdbc:postgresql://localhost:5432/db", "user", "pass");
PreparedStatement stmt = conn.prepareStatement("SELECT * FROM users WHERE id = ?")) {
stmt.setLong(1, 1L);
ResultSet rs = stmt.executeQuery();

while (rs.next()) {
System.out.println("User: " + rs.getString("name"));
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}


Это синхронно и блокирующе: executeQuery() "виснет" до ответа от БД, блокируя текущий поток.

В традиционных приложениях (как Spring MVC) это работало: каждый запрос — отдельный поток из пула (например, Tomcat с 200 потоками), и если БД отвечает быстро, проблем нет. Но под высокой нагрузкой или с медленными запросами (сетевые задержки, сложные джойны) пул исчерпывается: потоки "спят" в ожидании IO, CPU простаивает, а новые запросы ждут в очереди, вызывая таймауты и отказы. Это классическая проблема асинхронщины: JDBC не предназначен для non-blocking IO, он полагается на blocking calls операционной системы.

В реактивных приложениях (WebFlux) использование JDBC — антипаттерн: если контроллер возвращает Mono, но внутри — blocking JDBC, весь выигрыш теряется. Поток из event-loop (Netty) блокируется, снижая throughput (пропускную способность). Вот почему нужен новый подход.


Проблемы JDBC в реактивном контексте: почему старый стандарт не справляется

Давайте разберём проблемы JDBC подробно, чтобы понять мотивацию R2DBC:
Блокирующая природа: Все операции (connect, query, fetch) — синхронны. В асинхронном коде это требует обёрток вроде CompletableFuture или offload на отдельный пул (Schedulers.boundedElastic()), но это хак: теряется истинная реактивность, и под нагрузкой пулы переполняются.

Отсутствие backpressure: ResultSet — pull-модель (next() получает данные), но без контроля темпа. Если результат огромный (миллионы строк), буфер переполняется, рискуя OOM (OutOfMemoryError). В реактивном мире (push с backpressure) это несовместимо.

Управление соединениями: JDBC полагается на пулы (HikariCP), но они ориентированы на blocking: соединение "занято" весь запрос. В реактиве нужно multiplexing — одно соединение для многих операций асинхронно.

Транзакции:
@Transactional в Spring работает, но в реактиве требует специальной поддержки (reactive transactions), иначе — блокировки.

Масштабируемость: Под 10k+ RPS (requests per second) с БД-запросами JDBC требует огромных пулов потоков (тысячи), что жрёт память (каждый поток ~1MB стека) и контекст-свичинг.

Интеграция с Reactor: Нет native Publisher — результаты не "текут" как Flux, требуя ручной конвертации, что добавляет boilerplate и риски.


В итоге, JDBC — отличный для legacy или низконагруженных приложений, но в микросервисах с WebFlux он "ломает" реактивный стек, возвращая к болям callback-ада и ожиданий.


Введение в R2DBC: реактивный стандарт для реляционных БД

R2DBC — это спецификация (с 2019 года, под эгидой Spring и Pivotal), определяющая API для доступа к реляционным БД в реактивном стиле. Это не замена JDBC, а параллельный стандарт, ориентированный на non-blocking IO.

#Java #middle #Reactor #WebFlux #Mono #Flux #R2DBC
👍1
Ключевые идеи:
Publisher-based API: Все операции возвращают Publisher (Mono/Flux из Reactive Streams): Connection как Mono<Connection>, Statement.execute() как Flux<Row>.

Non-blocking от начала до конца: Использует асинхронные драйверы (для PostgreSQL, MySQL и т.д.), где соединения мультиплексируются — одно для многих запросов.

Backpressure встроено: Результаты (Flux<Row>) уважают request(n): если подписчик не готов, БД не шлёт данные, избегая перегрузки.

Транзакции реактивные: Поддержка
@Transactional с Mono/Flux.

Интеграция с экосистемой: Spring Data R2DBC — аналог Spring Data JPA, с репозиториями,
@Query и CRUD.

Драйверы: r2dbc-postgresql, r2dbc-mysql и т.д. — реализуют спецификацию, используя неблокирующие сокеты (Netty или аналог).

Пример базового R2DBC-кода (без Spring):
import io.r2dbc.spi.ConnectionFactories;
import io.r2dbc.spi.ConnectionFactory;
import reactor.core.publisher.Flux;

public void createConnectionFactory () {

ConnectionFactory factory = ConnectionFactories.get("r2dbc:postgresql://localhost:5432/db?username=user&password=pass");

Flux<String> namesFlux = Flux.usingWhen(

factory.create(), // Асинхронно создать соединение

conn -> conn.createStatement("SELECT name FROM users").execute().flatMap(result -> result.map((row, metadata) -> row.get("name", String.class))),
conn -> conn.close() // Асинхронно закрыть
);

namesFlux.subscribe(System.out::println); // Строки приходят асинхронно
}


Здесь usingWhen — реактивный try-with-resources: создаёт соединение асинхронно, выполняет запрос как Flux<Result>, map извлекает данные. Нет блокировок: если БД медленная, поток свободен.


Spring Data R2DBC: упрощение с репозиториями и аннотациями

Spring Data R2DBC — модуль, который абстрагирует R2DBC, как Spring Data JPA для JDBC.

Добавьте зависимость:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-r2dbc</artifactId>
</dependency>
<dependency>
<groupId>io.r2dbc</groupId>
<artifactId>r2dbc-postgresql</artifactId> <!-- Для PostgreSQL -->
</dependency>


Настройте в application.properties:
spring.r2dbc.url=r2dbc:postgresql://localhost:5432/db
spring.r2dbc.username=user
spring.r2dbc.password=pass


Репозитории:
ReactiveRepository extends ReactiveCrudRepository<Entity, ID>.


Сущность:
@Entity
public class User {
@Id
private Long id;
private String name;
// Getters/setters
}

public interface UserRepository extends ReactiveCrudRepository<User, Long> {
@Query("SELECT * FROM users WHERE name LIKE :name")
Flux<User> findByNameLike(String name);
}


В сервисе/контроллере:
@Service
public class UserService {
private final UserRepository repo;

public UserService(UserRepository repo) {
this.repo = repo;
}

public Flux<User> findAll() {
return repo.findAll(); // Flux асинхронно
}

public Mono<User> save(User user) {
return repo.save(user);
}
}


В контроллере:
@GetMapping("/users")
public Flux<User> getAllUsers() {
return userService.findAll();
}


Это декларативно: repo.findAll() — Flux, который "течёт" из БД без блокировок. Транзакции: @Transactional на методе — reactive, rollback асинхронно.

Расширенный пример: пагинация с ReactiveSortingRepository и Pageable.
public interface UserRepository extends ReactiveSortingRepository<User, Long> {}
Flux<User> paged = repo.findAll(Sort.by("name").ascending()).skip(10).take(20); // Простая пагинация
Для complex: используйте @Query с параметрами, или Criteria API.


Практические советы и подводные камни

Выбор БД: PostgreSQL — лучший для R2DBC (полная поддержка async).
Тестирование: Embedded H2 с r2dbc-h2, ReactiveTest для StepVerifier.
Камень: Нет full ORM (как JPA entities с relations) — используйте ручные joins или Spring Data Projections.
Камень: Транзакции не поддерживают propagation в nested методах fully — будьте осторожны.
Совет: Для hybrid (JDBC + R2DBC) — используйте разные DataSource, но избегайте в одном приложении.
Совет: Мониторьте с Micrometer: метрики на запросы, соединения.



#Java #middle #Reactor #WebFlux #Mono #Flux #R2DBC
👍1
Что выведет код?

import java.util.LinkedList;

public class Task221025 {
public static void main(String[] args) {
LinkedList<Integer> list = new LinkedList<>();
list.add(1);
list.add(2);
list.add(3);

list.remove(1);
list.remove(new Integer(2));

System.out.println(list.size());
System.out.println(list.get(0));
}
}


#Tasks
👍3
Варианты ответа:
Anonymous Quiz
22%
1 1
50%
1 3
11%
0
17%
2 1
👍1
Вопрос с собеседований

Что такое сериализация в Java? 🤓


Ответ:

Сериализация
— это преобразование объекта в поток байт для сохранения или передачи по сети.

Обратный процесс называется десериализацией. Реализуется через интерфейс Serializable.

Важно помнить о transient-полях и UID для совместимости.



#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
История IT-технологий сегодня — 23 октября


ℹ️ Кто родился в этот день

Андрей Карпатый (или Андрей Карпаты, англ. Andrej Karpathy, родился 23 октября 1986 года) — словацко-канадский учёный в области машинного обучения, который занимал должность директора по искусственному интеллекту в компании Tesla. Он является сооснователем и бывшим сотрудником OpenAI, где он специализировался на глубоком обучении и компьютерном зрении.


🌐 Знаковые события

Не нашел
(


#Biography #Birth_Date #Events #23Октября
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Раздел 6. Коллекции в Java

Глава 4. Queue и Deque

Интерфейс Deque. Двусторонняя очередь (FIFO и LIFO). Реализации: ArrayDeque, LinkedList

Интерфейс Deque<E> — это расширение Queue из пакета java.util, который представляет двустороннюю очередь (double-ended queue). Deque позволяет добавлять, удалять и просматривать элементы как с начала (head), так и с конца (tail) очереди. Это делает Deque универсальной структурой, способной моделировать как обычную очередь (FIFO), так и стек (LIFO), а также комбинированные сценарии.


Ключевые особенности Deque

Двусторонний доступ: Операции с first (начало) и last (конец).

FIFO и LIFO:
FIFO: Добавляйте в конец (addLast), извлекайте из начала (removeFirst) — как стандартная очередь.
LIFO: Добавляйте в начало (addFirst), извлекайте из начала (removeFirst) — как стек.


Уникальность элементов: Не гарантируется — дубликаты разрешены (зависит от реализации).
Null элементы: Зависит от реализации (ArrayDeque позволяет, но не рекомендуется; LinkedList позволяет).
Big O: Зависит от реализации, но обычно O(1) для операций на концах.
Итерация: Поддерживает Iterator для перебора от начала к концу, и descendingIterator() для обратного порядка.

Deque расширяет Queue, добавляя методы для работы с концом. Основные реализации: ArrayDeque (на массиве) и LinkedList (на связном списке). Deque можно использовать как Queue или Stack (вместо устаревшего Stack класса).

Когда использовать Deque:
Для стеков (LIFO, например, undo/redo).
Для очередей с доступом к концу (например, sliding window в алгоритмах).
Для двусторонних операций (например, палиндромы, где проверка с обоих концов).



FIFO и LIFO в Deque: Двусторонняя очередь

Deque поддерживает два основных режима:
FIFO (First-In-First-Out): "Первым вошел — первым вышел".

Добавление: addLast(E e) или offerLast(E e).
Извлечение: removeFirst() или pollFirst().
Просмотр: getFirst() или peekFirst().
Аналогия: Очередь в банке — первый пришел, первый ушел.


LIFO (Last-In-First-Out): "Последним вошел — первым вышел".

Добавление: addFirst(E e) или offerFirst(E e).
Извлечение: removeFirst() или pollFirst().
Просмотр: getFirst() или peekFirst().
Аналогия: Стопка тарелок — последняя сверху первой берется.



Методы Deque (основные, аналогично Queue, но с first/last)

Добавление:
addFirst(E e)/addLast(E e): Добавляет или кидает исключение, если переполнено.
offerFirst(E e)/offerLast(E e): Добавляет, возвращает boolean (false, если переполнено).


Извлечение:
removeFirst()/removeLast(): Извлекает или кидает NoSuchElementException, если пусто.
pollFirst()/pollLast(): Извлекает или возвращает null, если пусто.


Просмотр:
getFirst()/getLast(): Возвращает или кидает NoSuchElementException, если пусто.
peekFirst()/peekLast(): Возвращает или null, если пусто.


Другие: size(), isEmpty(), clear(), iterator(), descendingIterator().
Нюанс: Методы Queue (offer, poll, peek) в Deque эквивалентны offerLast, pollFirst, peekFirst (для FIFO).


#Java #для_новичков #beginner #Collections #Deque #ArrayDeque #LinkedList
👍3
Реализации Deque: ArrayDeque и LinkedList

ArrayDeque

Описание: ArrayDeque — эффективная реализация Deque на основе кругового массива (circular array), который resizable. Она оптимизирована для операций на концах и рекомендуется как стандартная Deque в Java.

Особенности:
FIFO/LIFO: Поддерживает оба.
Уникальность: Нет.
Null: Разрешен.
Big O: O(1) amortized для addFirst/addLast, removeFirst/removeLast, peek (постоянное время). Contains — O(n).


Внутренняя работа: Массив с head и tail индексами. При добавлении/удалении индексы циклически сдвигаются. При заполнении массив удваивается (resizing O(n) rarely).


Нюансы:
Память: Эффективнее LinkedList (нет ссылок на узлы).
Initial capacity: Конструктор с int для начального размера (default 16).
Thread-safety: Нет — используйте для single-thread.
Когда использовать: Для большинства Deque-задач (быстрее LinkedList для концов).
Ограничение: Не реализует List, нет доступа по индексу.


Пример кода для ArrayDeque:

import java.util.ArrayDeque;
import java.util.Deque;

public class Main {
public static void main(String[] args) {
Deque<String> deque = new ArrayDeque<>();
// FIFO: Очередь
deque.offerLast("Элемент 1"); // Добавление в конец
deque.offerLast("Элемент 2");
System.out.println(deque.pollFirst()); // Элемент 1 (извлечение из начала)
System.out.println(deque.peekFirst()); // Элемент 2 (просмотр)

// LIFO: Стек
deque.offerFirst("Элемент 3"); // Добавление в начало
deque.offerFirst("Элемент 4");
System.out.println(deque.pollFirst()); // Элемент 4 (LIFO)

// Обратный итератор
for (String elem : deque.descendingIterator()) {
System.out.println(elem); // С конца к началу
}
}
}

Вывод: Показывает FIFO и LIFO, операции O(1).


LinkedList

Описание: LinkedList — двусвязный список, который реализует Deque (и Queue, List). Как Deque, она позволяет операции на обоих концах.

Особенности:
FIFO/LIFO: Поддерживает оба.
Уникальность: Нет.
Null: Разрешен.
Big O: O(1) для addFirst/addLast, removeFirst/removeLast, peek (ссылки на first/last узлы). Contains — O(n).


Внутренняя работа: Узлы с prev/next ссылками. Добавление — создание узла и обновление ссылок first/last. Удаление — сдвиг ссылок.

Нюансы:
Память: Выше, чем ArrayDeque (каждый узел — объект с ссылками).
Универсальность: Реализует List, так что доступ по индексу (но O(n)).
Thread-safety: Нет.
Когда использовать: Для Deque с дополнительными List-функциями или частых вставок в середину (но для концов ArrayDeque быстрее).
Ограничение: Медленнее ArrayDeque для больших размеров из-за overhead узлов.


Пример кода для LinkedList как Deque (аналогичен ArrayDeque):
import java.util.LinkedList;
import java.util.Deque;

public class Main {
public static void main(String[] args) {
Deque<String> deque = new LinkedList<>();
deque.addLast("Элемент 1");
deque.addLast("Элемент 2");
System.out.println(deque.removeFirst()); // Элемент 1

deque.addFirst("Элемент 3");
System.out.println(deque.removeFirst()); // Элемент 3 (LIFO)
}
}

Вывод: То же, что и ArrayDeque, но с List-возможностями.


Полезные советы для новичков

ArrayDeque по умолчанию: Для большинства Deque-задач — эффективнее.
LinkedList для универсальности: Если нужно List API (get(index)), используйте её.
FIFO vs LIFO: Выбирайте методы (First/Last) по нуждам.
Null: Избегайте, чтобы не путаться.
Итераторы: descendingIterator() для обратного перебора — полезно для LIFO.



#Java #для_новичков #beginner #Collections #Deque #ArrayDeque #LinkedList
👍2
Что выведет код?

import java.util.ArrayDeque;
import java.util.Deque;

public class Task231025 {
public static void main(String[] args) {
Deque<Integer> deque = new ArrayDeque<>();
deque.offer(1);
deque.push(2);
deque.offer(3);
deque.push(4);

System.out.print(deque.poll() + " ");
System.out.print(deque.pop() + " ");
System.out.print(deque.remove() + " ");
System.out.print(deque.element());
}
}


#Tasks
👍1
Варианты ответа:
Anonymous Quiz
67%
4 2 1 3
17%
1 2 3 4
17%
4 3 2 1
0%
2 4 1 3
👍1
Вопрос с собеседований

Чем отличается shallow copy от deep copy? 🤓


Ответ:

Shallow copy
копирует только верхний уровень объекта (ссылки остаются общими).

Deep copy копирует и вложенные объекты, создавая полные независимые копии.

В Java shallow часто делается через clone(), а deep — через сериализацию или ручное копирование.



#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
История IT-технологий сегодня — 24 октября


ℹ️ Кто родился в этот день

Пьер Жиль де Жен (фр. Pierre-Gilles de Gennes; 24 октября 1932 года, Париж — 18 мая 2007, Орсе[фр.]) — французский физик, лауреат Нобелевской премии по физике в 1991 году. Де Жен известен прежде всего тем, что открыл структуру, положившую начало производству ЖК-дисплеев. За множество фундаментальных открытий члены Нобелевского комитета назвали де Жена «Ньютоном нашего времени».

Вернер Бухгольц (24 октября 1922 г. – 11 июля 2019 г.) — учёный-информатик германо-американского происхождения; работал в IBM, и в июне 1956 года ввёл термин «byte» (единица цифровой информации) для обозначения группы битов.

Чарльз Джозеф Колборн (родился 24 октября 1953 года) — канадский информатик и математик, специалист по графовым алгоритмам и комбинаторике, профессор в Arizona State University.


🌐 Знаковые события

1861 — по телеграфу передана первая в мире трансконтинентальная телеграмма — от судьи Стефана Дж. Филда (Stephen J. Field) из Калифорнии президенту США Аврааму Линкольну.

2007 — с космодрома Сичан с помощью ракеты-носителя Чанчжэн-3А запущена китайская АМС Чанъэ-1, предназначенная для исследования Луны.



#Biography #Birth_Date #Events #24Октября
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Реактивное программирование

Горячие и холодные Publisher’ы в реактивном программировании

Publisher — это источник данных в Reactive Streams, который "толкает" элементы подписчикам (Subscriber). Но не все Publisher’ы одинаковы по поведению при множественных подписках. Это зависит от того, генерирует ли он данные независимо от подписчиков (горячий) или заново для каждого (холодный).

Холодный Publisher (Cold Publisher): Данные генерируются лениво — только при подписке, и для каждого подписчика отдельно. Это как видео по запросу: каждый зритель получает свою копию потока. Плюс: свежие данные каждый раз. Минус: если источник дорогой (запрос в БД, вычисления), повторяется зря.

Горячий Publisher (Hot Publisher): Данные генерируются независимо от подписчиков — поток "вещает" непрерывно. Подписчики "подключаются" к существующему потоку и получают данные с момента подписки. Это как живой эфир: все слушают одно и то же, но опоздавшие пропускают начало. Плюс: экономия ресурсов (один источник). Минус: данные могут быть "старыми" или пропущенными.


В Project Reactor большинство конструкторов — холодные (just, fromIterable, range), но есть горячие (interval, push). Поведение можно менять операторами (share, cache).


Примеры холодных Publisher’ов: ленивость и независимость

Холодные — default в Reactor: подписка запускает генерацию заново.


Пример с Mono (одиночный элемент, но принцип тот же):
Mono<String> coldMono = Mono.fromCallable(() -> {
System.out.println("Генерация данных...");
return "Данные";
});

coldMono.subscribe(System.out::println); // Вывод: "Генерация данных..." и "Данные"
coldMono.subscribe(System.out::println); // Снова: "Генерация данных..." и "Данные"
Каждый subscribe() вызывает fromCallable заново — данные свежие, но если это запрос в API, будет два вызова.


С Flux:
   Flux<Integer> coldFlux = Flux.range(1, 3).doOnSubscribe(sub -> System.out.println("Новая подписка!"));
coldFlux.subscribe(val -> System.out.println("Подписчик 1: " + val));
coldFlux.subscribe(val -> System.out.println("Подписчик 2: " + val));
// Вывод: "Новая подписка!" + 1,2,3 для первого; "Новая подписка!" + 1,2,3 для второго

Каждый подписчик получает полный поток независимо. Полезно для idempotent операций (без side-effects), как чтение статичных данных.
Асинхронный пример: coldFlux = Flux.interval(Duration.ofSeconds(1)).take(3); // Каждый subscribe() запускает свой таймер.


Примеры горячих Publisher’ов: общий поток и вещание

Горячие — генерируют данные один раз, подписчики "присоединяются".


Пример с Flux.push (горячий по дизайну):
ConnectableFlux<Integer> hotFlux = Flux.push(sink -> {
// Симулируем внешний источник
new Thread(() -> {
for (int i = 1; i <= 3; i++) {
try { Thread.sleep(1000); } catch (InterruptedException e) {}
sink.next(i);
}
sink.complete();
}).start();
});

hotFlux.subscribe(val -> System.out.println("Подписчик 1: " + val));
Thread.sleep(1500); // Ждём, чтобы пропустить начало
hotFlux.subscribe(val -> System.out.println("Подписчик 2: " + val));
hotFlux.connect(); // Запуск горячего

// Вывод примерно: Подписчик 1: 1 (1с), 2 (2с), 3 (3с); Подписчик 2: 2 (присоединился после 1), 3

Второй пропустил 1 — поток общий. Connect() — триггер для ConnectableFlux (обёртка для горячих).


Другой горячий:
Flux.interval(Duration.ofSeconds(1)) — бесконечный таймер, вещает независимо.
Оператор share(): Делает холодный горячим.
Flux<Integer> shared = coldFlux.share();
shared.subscribe(...); // Запускает
shared.subscribe(...); // Присоединяется к существующему



#Java #middle #Reactor #WebFlux #Mono #Flux
👍2
Переключение типов: операторы для контроля

Из холодного в горячий: share() (для Flux), cache() (кэширует элементы для повторов), publish() (ConnectableFlux с backpressure).

Пример cache:
coldMono.cache() — первый subscribe генерирует, последующие — из кэша.
Из горячего в холодный: Редко нужно, но replay() на ConnectableFlux кэширует историю для новых подписчиков.


Сценарии:
Холодный: Запросы к БД (каждый клиент — свежие данные).
Горячий: Мониторинг (один сенсор — всем подписчикам), стриминг событий (Kafka topic).


Практические советы и подводные камни


Диагностика: doOnSubscribe(() -> log("Subscribe")) — увидите, сколько раз запускается.
Камень: Холодный с side-effects (мутации) — непредсказуемо при множественных подписках; используйте defer() для ленивости.
Камень: Горячий бесконечный без take() — утечки; добавьте refCount() на publish() для авто-отписки при 0 подписчиках.
Совет: В WebFlux — Flux из БД (R2DBC, пост 17) холодный по умолчанию; share() для кэширования результатов.
Тестирование: StepVerifier с .publish() для симуляции горячих.



#Java #middle #Reactor #WebFlux #Mono #Flux
👍2
Что выведет код?

import java.util.concurrent.*;

public class Task241025 {
public static void main(String[] args) throws InterruptedException {
BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(2);

System.out.print(queue.offer(1) + " ");
System.out.print(queue.offer(2) + " ");
System.out.print(queue.offer(3, 100, TimeUnit.MILLISECONDS) + " ");

System.out.print(queue.poll() + " ");
System.out.print(queue.offer(3) + " ");
System.out.print(queue.poll() + " ");
System.out.print(queue.poll() + " ");
}
}


#Tasks
👍1
Вопрос с собеседований

Чем отличается checked cast от instanceof + cast? 🤓


Ответ:

Checked cast
((String) obj) может выбросить ClassCastException.

Использование instanceof позволяет сначала проверить тип, а затем безопасно привести объект.

Это предотвращает ошибки в рантайме.



#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2