Java | Вопросы собесов
11.4K subscribers
37 photos
3 videos
1.53K links
Сайт: https://easyoffer.ru/
Все каналы: t.me/+xGeAw6ckJ4liYzQy

Контакт для рекламы: @easyoffer_adv
Download Telegram
🤔 В чем разница Spring Boot и Spring?

Spring и Spring Boot являются частью экосистемы, которая предоставляет широкий спектр инструментов для разработки современных Java-приложений. Несмотря на тесную связь, между ними есть ключевые отличия.

🚩Spring Framework

Это мощный и широко используемый фреймворк для разработки приложений на Java. Он предоставляет обширный набор функциональностей, включая инверсию управления (IoC) и внедрение зависимостей (DI), абстракции для работы с транзакциями, обработку исключений, поддержку аспектно-ориентированного программирования (AOP) и многое другое. Он предназначен для упрощения Java EE разработки, обеспечивая легкость создания масштабируемых и легко поддерживаемых приложений.

🚩Spring Boot

С другой стороны, представляет собой расширение Spring Framework, предназначенное для упрощения процесса конфигурации и развертывания Spring-приложений. Он автоматизирует многие процессы, предоставляя "готовые к использованию" настройки для быстрого старта проектов и избавления от необходимости вручную определять стандартную конфигурацию.

🚩Различия

🟠Цель
Spring Framework предоставляет основу для создания приложений на Java, в то время как Spring Boot предлагает конвенции и автоматическую конфигурацию для быстрого старта и развертывания приложений.

🟠Конфигурация
В Spring для настройки приложения часто требуется детальная конфигурация, включая XML-файлы или аннотации. Spring Boot стремится уменьшить эту сложность, автоматически конфигурируя компоненты на основе добавленных в проект зависимостей.

🟠Встроенный сервер
Spring Boot по умолчанию включает в себя встроенный сервер приложений, что упрощает развертывание и тестирование веб-приложений.

Ставь 👍 и забирай 📚 Базу знаний
👍4
🤔 Как бы реализовал отправку сообщения клиенту, учитывая возможность отмены транзакции?

Один из надёжных подходов:
1. В транзакции записать сообщение в таблицу "очередь на отправку".
2. После успешного коммита — отдельный процесс/воркер читает сообщения из таблицы и отправляет.
3. Если транзакция откатилась — сообщение не будет отправлено.
Это позволяет гарантировать согласованность между бизнес-операцией и отправкой.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
🔥4👍1
🤔 Назови основные свойства транзакции

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

🚩Атомарность (Atomicity) — "всё или ничего"
Транзакция выполняется полностью или не выполняется вовсе.
Перевод 1000 рублей с одного счёта на другой:
- Списать 1000 рублей с А
- Зачислить 1000 рублей на B
Если вторая операция не удалась, первая должна быть отменена.
try {
connection.setAutoCommit(false); // Отключаем автокоммит
withdraw(accountA, 1000);
deposit(accountB, 1000);
connection.commit(); // Подтверждаем транзакцию
} catch (Exception e) {
connection.rollback(); // Откат в случае ошибки
}


🚩Согласованность (Consistency) — "данные остаются корректными"

После транзакции данные должны оставаться в логически правильном состоянии.

🚩Изолированность (Isolation) — "отдельно от других транзакций"

Одна транзакция не должна мешать выполнению другой.
Два клиента одновременно бронируют одно и то же место в самолёте.
Система должна обработать их по очереди, а не одновременно.
В Java изолированность регулируется уровнями транзакций (TRANSACTION_READ_COMMITTED, TRANSACTION_REPEATABLE_READ и т. д.), чтобы избежать проблем, таких как "грязное чтение" или "фантомные записи".
connection.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ);


🚩Долговечность (Durability) — "данные не теряются"

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

Ставь 👍 и забирай 📚 Базу знаний
👍3
🤔 Какие преимущества придаёт Iterable?

- Позволяет использовать for-each цикл.
- Обеспечивает единый способ итерирования по коллекциям.
- Требует реализации метода iterator().


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
👍3
🤔 Какие минусы Rest в высоконагруженных сис-мах?

REST – это удобный и популярный архитектурный стиль, но в высоконагруженных системах у него есть недостатки.

🚩Высокие накладные расходы HTTP (избыточность)

Проблема: Каждый REST-запрос передаёт много мета-информации (заголовки, cookies, CORS, JSON/XML).
GET /users/123 HTTP/1.1
Host: api.example.com
Authorization: Bearer token123
Content-Type: application/json


В WebSocket/gRPC запрос выглядел бы так
{ "userId": 123 }


🚩REST-запросы неэффективны для чатов и real-time

Проблема: REST использует "запрос-ответ", но **не поддерживает real-time.

Что происходит в REST?
1. Клиент делает HTTP-запрос к серверу.
2. Сервер обрабатывает и отправляет ответ.
3. Если клиенту нужно новое сообщение, он снова делает запрос (Polling) или использует Long Polling.

🚩Проблемы с кэшированием

Проблема: Не все REST-запросы можно кэшировать.
Кэшируются только GET-запросы (если сервер поддерживает ETag и Cache-Control).
POST, PUT, DELETE – не кэшируются, потому что меняют данные.

🚩REST API неэффективен для сложных запросов

Проблема: REST требует много отдельных запросов, если нужно загрузить связанные данные.
Пример проблемы REST:
Получить пользователя: /users/123
Получить заказы этого пользователя: /users/123/orders
Получить детали заказов: /orders/456/details

Ставь 👍 и забирай 📚 Базу знаний
👍4
🤔 Какая сложность поиска элемента в LinkedList?

Сложность поиска по индексу в LinkedList — O(n).
Это потому, что LinkedList — это цепочка узлов, и для доступа к элементу приходится перебирать узлы по одному от начала (или конца, если ближе).


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
👍5💊1
🤔 Что знаешь про поверхностное копирование?

Поверхностное копирование (Shallow Copy) – это процесс создания нового объекта, который содержит ссылки на те же вложенные объекты, что и оригинал.

🟠Как сделать поверхностное копирование в Java?
Способ 1: Метод clone() (реализация Cloneable)
class Person implements Cloneable {
String name;

public Person(String name) {
this.name = name;
}

@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone(); // Поверхностное копирование
}
}

public class Main {
public static void main(String[] args) throws CloneNotSupportedException {
Person original = new Person("Иван");
Person copy = (Person) original.clone();

System.out.println(copy.name); // Иван
}
}


🟠Проблема с вложенными объектами (общие ссылки)
Если объект содержит вложенные объекты, они не копируются, а передаются по ссылке.
class Address {
String city;
public Address(String city) { this.city = city; }
}

class User implements Cloneable {
String name;
Address address;

public User(String name, Address address) {
this.name = name;
this.address = address;
}

@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone(); // Поверхностное копирование
}
}

public class Main {
public static void main(String[] args) throws CloneNotSupportedException {
Address address = new Address("Москва");
User original = new User("Иван", address);
User copy = (User) original.clone();

copy.address.city = "Санкт-Петербург"; // Меняем адрес у копии

System.out.println(original.address.city); // Санкт-Петербург (изменилось и у оригинала!)
}
}


🟠Как сделать глубокую копию? (Deep Copy)
Решение: Создать новый вложенный объект в clone()
@Override
protected Object clone() throws CloneNotSupportedException {
User clonedUser = (User) super.clone();
clonedUser.address = new Address(this.address.city); // Копируем вложенный объект
return clonedUser;
}


Ставь 👍 и забирай 📚 Базу знаний
👍1
🤔 Для чего нужны паттерны программирования?

Паттерны — это решения типичных задач разработки. Они:
- повышают читаемость кода;
- упрощают поддержку;
- помогают писать гибкие и масштабируемые архитектуры;
- облегчают коммуникацию между разработчиками.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
👍3💊1
🤔 Что такое as-if-serial semantics?

As-If-Serial Semantics – это принцип оптимизации компилятором, при котором код может перестраиваться, но результат его выполнения остаётся таким же, как если бы инструкции выполнялись строго по порядку.

Обычный код
int a = 10;
int b = 20;
int c = a + b;
System.out.println(c);


Что может сделать компилятор?
int c = 30;
System.out.println(c);


🚩Что можно менять? (Безопасные оптимизации)

Менять порядок инструкций, если это не влияет на результат.
Удалять лишние переменные и вычисления.
Заменять выражения константами (10 + 20 → 30).
int x = 5;
int y = 10;
x = x + 1; // x = 6
System.out.println(y);


Компилятор может поменять местами y и x
int y = 10;
int x = 6;
System.out.println(y);


🚩Что нельзя менять? (Гарантированный порядок исполнения)

int x = 10;
int y = x + 5;
x = 20;
System.out.println(y);


Если поменять порядок
x = 20;
int y = x + 5; // Неверно! y теперь 25, а должно быть 15


🚩Как `As-If-Serial` влияет на многопоточность?

В многопоточной среде компилятор может менять порядок команд внутри одного потока, но он не знает о другом потоке!
Опасный пример без volatile
boolean ready = false;
int data = 0;

void writer() {
data = 42;
ready = true;
}

void reader() {
if (ready) {
System.out.println(data); // Может напечатать 0 из-за перестановки!
}
}


Решение – volatile для ready
volatile boolean ready = false;


Ставь 👍 и забирай 📚 Базу знаний
👍2
🤔 Какое базовое отличие между интерфейсами Collection и List?

- Collection — базовый интерфейс, представляющий неупорядоченное множество элементов. Он не знает про индексы, дубликаты или порядок.
- List — расширяет Collection, добавляя:
- упорядоченность элементов;
- доступ по индексу;
- поддержку дубликатов.
То есть List — это частный случай Collection, который работает как последовательность с доступом по позиции.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
👍3🔥1
🤔 Какая скорость доступа к элементу в LinkedList по индексу?

Доступ к элементу по индексу в LinkedList занимает O(n).
Чтобы получить элемент, LinkedList начинает обход с начала (или конца, если индекс ближе к нему), переходя от узла к узлу. Чем ближе к началу/концу — тем быстрее.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
👍4
🤔 В чём заключается разница между методами start() и run()?

🚩`start()` – создаёт новый поток

Метод start() создаёт новый поток и вызывает run() внутри него.
class MyThread extends Thread {
@Override
public void run() {
System.out.println("Работает поток: " + Thread.currentThread().getName());
}
}

public class Main {
public static void main(String[] args) {
MyThread thread = new MyThread();
thread.start(); // Запускаем новый поток

System.out.println("Работает поток: " + Thread.currentThread().getName());
}
}


Вывод (разные потоки работают параллельно)
Работает поток: main
Работает поток: Thread-0


🚩`run()` – выполняется в ТЕКУЩЕМ потоке (без создания нового)

Если вызвать run() напрямую, код просто выполнится как обычный метод, а не в новом потоке.
public class Main {
public static void main(String[] args) {
MyThread thread = new MyThread();
thread.run(); // Ошибка! Работает в главном потоке

System.out.println("Работает поток: " + Thread.currentThread().getName());
}
}


Вывод (run() работает в главном потоке, а не в новом)
Работает поток: main
Работает поток: main


Ставь 👍 и забирай 📚 Базу знаний
👍4
🤔 Известно ли про классы-обёртки?

Integer, Boolean, Double и др.
Позволяют:
- Использовать примитивы как объекты.
- Работать с дженериками.
- Предоставляют вспомогательные методы.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
🤔5👍2
🤔 Какая коллекция реализует дисциплину обслуживания FIFO?

FIFO (First-In, First-Out) – это принцип обработки данных: "первым вошёл – первым вышел".

🟠Коллекции, реализующие FIFO
Пример работы FIFO с Queue
import java.util.*;

public class FifoExample {
public static void main(String[] args) {
Queue<String> queue = new LinkedList<>(); // Можно заменить на ArrayDeque

queue.add("Первый");
queue.add("Второй");
queue.add("Третий");

System.out.println(queue.poll()); // Первый
System.out.println(queue.poll()); // Второй
System.out.println(queue.poll()); // Третий
}
}


🟠Разница `poll()`, `remove()` и `peek()`
Queue<Integer> queue = new LinkedList<>();
queue.add(10);
System.out.println(queue.peek()); // 10 (но не удаляет)
System.out.println(queue.poll()); // 10 (удаляет)
System.out.println(queue.poll()); // null (очередь пуста)


Ставь 👍 и забирай 📚 Базу знаний
👍3
🤔 Какие конечные методы работы со стримами есть?

- forEach(), forEachOrdered();
- collect();
- toArray();
- reduce();
- count();
- min(), max();
- anyMatch(), allMatch(), noneMatch();
- findFirst(), findAny().


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
👍4🔥1
🤔 Как найти ошибку в программе?

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

1⃣Понимание ошибки
Симптомы ошибки: Программа выдает ошибочное поведение, например, неожиданный результат, исключение или сбой.
Типы ошибок:
Синтаксические: Ошибки в написании кода (например, пропущенная точка с запятой).
Логические: Код выполняется без ошибок, но результат не соответствует ожиданиям.
Ошибки выполнения: Программа завершает работу из-за исключения (например, деление на ноль).

2⃣Использование сообщений об ошибках
Компилятор/интерпретатор: Сообщает о синтаксических ошибках и указывает строку, где возникла проблема.
Стек вызовов (stack trace): Для ошибок выполнения предоставляет информацию о том, где произошла ошибка.
Пример:
Exception in thread "main" java.lang.ArithmeticException: / by zero
at Main.main(Main.java:5)


3⃣Ручное исследование кода
Прочитайте проблемный участок кода и проверьте его на соответствие логике задачи.
Ищите типичные ошибки, такие как:
Неправильное использование переменных.
Ошибки в условных операторах (if, switch).
Пропущенные или лишние элементы кода.

4⃣Использование инструментов отладки
Отладчик (Debugger):
Отладчики встроены в IDE, такие как IntelliJ IDEA, Eclipse или NetBeans.
Позволяют ставить точки останова (breakpoints), чтобы программа останавливалась в конкретных местах.
Позволяют пошагово выполнять код и проверять значения переменных.
Логирование (Logging):
Используйте System.out.println для вывода промежуточных данных:

       System.out.println("Value of x: " + x);


Пример

     import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Main {
private static final Logger logger = LoggerFactory.getLogger(Main.class);

public static void main(String[] args) {
int x = 10;
int y = 0;
try {
int result = x / y;
} catch (ArithmeticException e) {
logger.error("Division by zero!", e);
}
}
}


5⃣Тестирование
Покрытие тестами: Напишите автоматические тесты для выявления ошибки.
Используйте фреймворки, такие как JUnit или TestNG.

       import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;

public class CalculatorTest {
@Test
void testAddition() {
assertEquals(5, Calculator.add(2, 3));
}
}


6⃣Анализ чужого кода
Если ошибка в сторонней библиотеке, проверьте документацию и известные проблемы. Убедитесь, что вы правильно используете методы и классы.

7⃣Рефакторинг и исправление
Исправьте ошибку, убедившись, что исправление не приводит к новым ошибкам. Проверьте весь код на предмет аналогичных ошибок.

Ставь 👍 и забирай 📚 Базу знаний
👍2🔥1
🤔 Что такое партиционирование?

Это разделение таблицы на логические части (партиции) для улучшения производительности и управляемости.
1. Партиции могут быть основаны на диапазонах, хэшах или списках значений.
2. Улучшает производительность запросов, снижая объём обрабатываемых данных.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
👍6
🤔 Как бороться в БД с SQL Injection?

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

Допустим, у нас есть код
String query = "SELECT * FROM users WHERE username = '" + username + "' AND password = '" + password + "'";


Если злоумышленник введёт ' OR '1'='1 в поле пароля, запрос превратится в:
SELECT * FROM users WHERE username = 'admin' AND password = '' OR '1'='1'


🚩Способы защиты от SQL Injection

🟠Использование `PreparedStatement` (РЕКОМЕНДУЕТСЯ)
Подготовленные запросы автоматически экранируют входные данные, предотвращая SQL-инъекции.
String sql = "SELECT * FROM users WHERE username = ? AND password = ?";
PreparedStatement stmt = connection.prepareStatement(sql);
stmt.setString(1, username);
stmt.setString(2, password);
ResultSet rs = stmt.executeQuery();


🟠Использование ORM (например, Hibernate)
ORM-фреймворки (Hibernate, JPA) автоматически генерируют безопасные SQL-запросы.
TypedQuery<User> query = entityManager.createQuery(
"SELECT u FROM User u WHERE u.username = :username AND u.password = :password", User.class);
query.setParameter("username", username);
query.setParameter("password", password);
User user = query.getSingleResult();


🟠Проверка и экранирование входных данных
Если по какой-то причине PreparedStatement использовать нельзя, экранируйте опасные символы (', " и ;).
String safeInput = input.replace("'", "\\'");


🟠Минимизация прав в БД
Создавайте отдельного пользователя БД с ограниченными правами:
Запрет на DROP, DELETE, UPDATE без WHERE
Только доступ к нужным таблицам
CREATE USER 'app_user'@'localhost' IDENTIFIED BY 'securepassword';
GRANT SELECT, INSERT, UPDATE ON mydb.users TO 'app_user'@'localhost';


🟠Использование Web Application Firewall (WAF)
WAF анализирует HTTP-запросы и блокирует подозрительные SQL-запросы. Пример: ModSecurity – популярный WAF для защиты веб-приложений.

Ставь 👍 и забирай 📚 Базу знаний
👍3🔥1
🤔 Какое худшее время работы метода contains() в ArrayList?

O(n) — также линейный поиск, т.к. нет хеширования.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
👍2
🤔 Для чего нужен функциональный интерфейс BiConsumer<T,U>?

BiConsumer<T, U> — это функциональный интерфейс из пакета java.util.function, который принимает два входных аргумента и не возвращает результат.

Сигнатура BiConsumer<T, U>
@FunctionalInterface
public interface BiConsumer<T, U> {
void accept(T t, U u);
}


🚩Вывод пар значений

Допустим, у нас есть Map<String, Integer>, и мы хотим вывести все ключи и значения:
import java.util.Map;
import java.util.function.BiConsumer;

public class BiConsumerExample {
public static void main(String[] args) {
Map<String, Integer> map = Map.of("Alice", 30, "Bob", 25, "Charlie", 35);

// Используем BiConsumer для вывода ключа и значения
BiConsumer<String, Integer> printEntry = (key, value) ->
System.out.println("Имя: " + key + ", возраст: " + value);

// Применяем BiConsumer к каждому элементу Map
map.forEach(printEntry);
}
}


Вывод
Имя: Alice, возраст: 30  
Имя: Bob, возраст: 25
Имя: Charlie, возраст: 35


🚩Использование `BiConsumer` в `Stream`

Допустим, у нас есть список продуктов и их цены. Мы хотим увеличить цену каждого товара и напечатать результат.
import java.util.*;
import java.util.function.BiConsumer;

public class BiConsumerStreamExample {
public static void main(String[] args) {
Map<String, Double> products = new HashMap<>();
products.put("Хлеб", 50.0);
products.put("Молоко", 80.0);
products.put("Яблоки", 120.0);

// BiConsumer, который увеличивает цену и выводит её
BiConsumer<String, Double> increaseAndPrint = (name, price) -> {
double newPrice = price * 1.1; // +10%
System.out.println(name + " теперь стоит " + newPrice);
};

products.forEach(increaseAndPrint);
}
}


Вывод
Хлеб теперь стоит 55.0  
Молоко теперь стоит 88.0
Яблоки теперь стоят 132.0


🚩Объединение `BiConsumer` с `andThen()`

Метод andThen(BiConsumer<T, U>) позволяет объединять несколько действий в цепочку.
import java.util.function.BiConsumer;

public class BiConsumerChaining {
public static void main(String[] args) {
BiConsumer<String, Integer> printUser = (name, age) ->
System.out.println("Пользователь: " + name + ", возраст: " + age);

BiConsumer<String, Integer> checkAdult = (name, age) ->
System.out.println(name + (age >= 18 ? " совершеннолетний" : " несовершеннолетний"));

// Объединяем два BiConsumer'а
BiConsumer<String, Integer> combined = printUser.andThen(checkAdult);

combined.accept("Алексей", 20);
combined.accept("Мария", 16);
}
}


Вывод:
Пользователь: Алексей, возраст: 20  
Алексей совершеннолетний
Пользователь: Мария, возраст: 16
Мария несовершеннолетний


Ставь 👍 и забирай 📚 Базу знаний
👍4
🤔 Что такое шаблон Event Sourcing?

Event Sourcing — это подход, при котором вся история изменений состояния хранится как последовательность событий.
Плюсы:
- можно восстановить любое состояние;
- идеален для аудита и CQRS.
Минусы:
- сложно мигрировать;
- высокая сложность чтения без проекций.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
🔥2