🤔 Как используется SOLID принцип открытости-закрытости при проектировании?
Принцип открытости-закрытости (Open-Closed Principle) предполагает, что программные сущности должны быть открыты для расширения, но закрыты для модификации. Это достигается через использование абстракций, интерфейсов и наследования.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Принцип открытости-закрытости (Open-Closed Principle) предполагает, что программные сущности должны быть открыты для расширения, но закрыты для модификации. Это достигается через использование абстракций, интерфейсов и наследования.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
👍12
🤔 Расскажи про Hash Code & Equals Contract
Когда вы переопределяете методы
🚩Контракт `equals()`
Метод
Рефлексивность –
Симметричность –
Транзитивность – если
Согласованность – многократные вызовы
Сравнение с
🚩Контракт `hashCode()`
Метод
Если
Если
Хеш-код должен оставаться неизменным, если объект не изменяется.
🚩Почему контракт `equals()` и `hashCode()` важен?
В коллекциях, таких как
Что будет, если
Правильный вариант (
Ставь 👍 и забирай 📚 Базу знаний
Когда вы переопределяете методы
equals() и hashCode(), важно соблюдать контракт, иначе объект может вести себя некорректно в коллекциях (HashMap, HashSet и др.). 🚩Контракт `equals()`
Метод
equals() определяет, когда два объекта равны. Рефлексивность –
x.equals(x) всегда true. Симметричность –
x.equals(y) == y.equals(x). Транзитивность – если
x.equals(y) и y.equals(z), то x.equals(z). Согласованность – многократные вызовы
x.equals(y) дают один и тот же результат. Сравнение с
null всегда false – x.equals(null) == false. class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true; // Проверка на одинаковые ссылки
if (obj == null || getClass() != obj.getClass()) return false; // Проверка типа
Person person = (Person) obj;
return age == person.age && name.equals(person.name); // Сравнение полей
}
}🚩Контракт `hashCode()`
Метод
hashCode() возвращает числовой хеш-код объекта. Он должен соответствовать equals()! Если
x.equals(y) == true, то x.hashCode() == y.hashCode(). Если
x.hashCode() != y.hashCode(), то x.equals(y) == false (но обратное не всегда верно). Хеш-код должен оставаться неизменным, если объект не изменяется.
@Override
public int hashCode() {
return Objects.hash(name, age);
}
🚩Почему контракт `equals()` и `hashCode()` важен?
В коллекциях, таких как
HashSet, HashMap, HashTable, объекты хранятся по хеш-коду. Что будет, если
equals() переопределён, но hashCode() – нет? Set<Person> people = new HashSet<>();
people.add(new Person("Иван", 25));
people.add(new Person("Иван", 25)); // Ожидаем, что не добавится
System.out.println(people.size()); // ❌ Будет 2, а не 1, если `hashCode()` отсутствует!
Правильный вариант (
equals() + hashCode()) class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
Person person = (Person) obj;
return age == person.age && name.equals(person.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}Ставь 👍 и забирай 📚 Базу знаний
👍6🤔3
🤔 В чём разница между Dependency Injection и инверсией управления?
Inversion of Control (IoC) — это общая концепция, при которой внешняя система управляет созданием и связыванием объектов.
Dependency Injection (DI) — это конкретный способ реализации IoC, при котором зависимости:
- внедряются в объект через:
- конструктор;
- поле;
- метод.
Иными словами:
- IoC — это философия.
- DI — это инструмент.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Inversion of Control (IoC) — это общая концепция, при которой внешняя система управляет созданием и связыванием объектов.
Dependency Injection (DI) — это конкретный способ реализации IoC, при котором зависимости:
- внедряются в объект через:
- конструктор;
- поле;
- метод.
Иными словами:
- IoC — это философия.
- DI — это инструмент.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
👍14🔥6
🤔 Чем отличается компонент от бина?
В Spring оба термина – Bean и Component – связаны с управляемыми объектами, но у них разное предназначение.
🚩Что такое `@Component`?
Spring сам создаст и зарегистрирует объект в контейнере.
Как получить объект?
🚩Что такое `@Bean`?
Можно использовать, если нужно передать параметры или создать Bean из библиотеки.
Как получить Bean?
Ставь 👍 и забирай 📚 Базу знаний
В Spring оба термина – Bean и Component – связаны с управляемыми объектами, но у них разное предназначение.
🚩Что такое `@Component`?
@Component делает класс Spring-бином автоматически. Spring сам создаст и зарегистрирует объект в контейнере.
import org.springframework.stereotype.Component;
@Component
public class Car {
public void drive() {
System.out.println("Машина едет...");
}
}
Как получить объект?
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Main {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
Car car = context.getBean(Car.class);
car.drive();
}
}
🚩Что такое `@Bean`?
@Bean создаёт Bean вручную в @Configuration-классе. Можно использовать, если нужно передать параметры или создать Bean из библиотеки.
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AppConfig {
@Bean
public Car car() {
return new Car(); // Создаём объект вручную
}
}
Как получить Bean?
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
Car car = context.getBean(Car.class);
Ставь 👍 и забирай 📚 Базу знаний
👍4
🤔 Чем отличается композиция от наследования?
- Наследование — это отношение "является", позволяет использовать поведение родительского класса.
- Композиция — это отношение "имеет", позволяет встраивать поведение других объектов и менять их без изменения иерархии. Композиция более гибкая и предпочтительна при проектировании.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
- Наследование — это отношение "является", позволяет использовать поведение родительского класса.
- Композиция — это отношение "имеет", позволяет встраивать поведение других объектов и менять их без изменения иерархии. Композиция более гибкая и предпочтительна при проектировании.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
👍4🔥1💊1
🤔 Чем отличаются методы Thread.sleep() и Thread.yield()?
Методы
🚩Thread.sleep()
Метод
🚩Как это работает?
Поток уходит в состояние "ожидания" (TIMED_WAITING).
Операционная система не даёт ему процессорное время в течение заданного времени.
После завершения паузы поток снова становится готовым к выполнению (RUNNABLE).
Результат
🚩Thread.yield()
Метод
🚩Как это работает?
Текущий поток передаёт управление планировщику (scheduler).
Если есть другие потоки с таким же или более высоким приоритетом, они получат процессорное время.
Если таких потоков нет, то текущий поток продолжит выполняться.
Результат (примерный, зависит от планировщика ОС)
Ставь 👍 и забирай 📚 Базу знаний
Методы
Thread.sleep() и Thread.yield() в Java используются для управления потоком, но работают по-разному. 🚩Thread.sleep()
Метод
Thread.sleep(milliseconds) приостанавливает выполнение текущего потока на указанное время. 🚩Как это работает?
Поток уходит в состояние "ожидания" (TIMED_WAITING).
Операционная система не даёт ему процессорное время в течение заданного времени.
После завершения паузы поток снова становится готовым к выполнению (RUNNABLE).
public class SleepExample {
public static void main(String[] args) {
System.out.println("Начало работы...");
try {
Thread.sleep(2000); // Пауза на 2 секунды
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Прошло 2 секунды");
}
}Результат
Начало работы...
(пауза 2 секунды)
Прошло 2 секунды
🚩Thread.yield()
Метод
Thread.yield() даёт возможность другим потокам выполнить работу. 🚩Как это работает?
Текущий поток передаёт управление планировщику (scheduler).
Если есть другие потоки с таким же или более высоким приоритетом, они получат процессорное время.
Если таких потоков нет, то текущий поток продолжит выполняться.
public class YieldExample {
public static void main(String[] args) {
Runnable task = () -> {
for (int i = 1; i <= 5; i++) {
System.out.println(Thread.currentThread().getName() + " - " + i);
Thread.yield(); // Позволяет другим потокам выполняться
}
};
Thread t1 = new Thread(task, "Поток-1");
Thread t2 = new Thread(task, "Поток-2");
t1.start();
t2.start();
}
}Результат (примерный, зависит от планировщика ОС)
Поток-1 - 1
Поток-2 - 1
Поток-1 - 2
Поток-2 - 2
...
Ставь 👍 и забирай 📚 Базу знаний
👍4
🤔 Request мы можем использовать во всех Spring приложениях?
Нет. Объект HttpServletRequest и скоуп request доступны только в веб-приложениях на Spring MVC или Spring Boot.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Нет. Объект HttpServletRequest и скоуп request доступны только в веб-приложениях на Spring MVC или Spring Boot.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
👍7
🤔 Что должно быть если объект equals нал?
Метод
🚩Почему важно обрабатывать `null` в `equals()`?
🟠Контракт метода `equals()`
Согласно спецификации Java, метод
Симметричность: Если
Для
🟠Предотвращение `NullPointerException`
Если метод
🚩Как правильно реализовать метод `equals()`?
Вот стандартный способ реализации метода
🚩Что происходит, если игнорировать проверку `null`?
Если вы не проверяете
Пример с проверкой
Ставь 👍 и забирай 📚 Базу знаний
Метод
equals() в Java предназначен для проверки равенства двух объектов. Если объект, переданный в метод equals(), равен null, метод должен возвращать `false`, так как объект не может быть равен null по определению. Рассмотрим этот случай более подробно.🚩Почему важно обрабатывать `null` в `equals()`?
🟠Контракт метода `equals()`
Согласно спецификации Java, метод
equals() должен возвращать false, если объект, переданный в метод, равен null. Это необходимо для корректного сравнения объектов.Симметричность: Если
a.equals(b) возвращает true, то b.equals(a) также должно возвращать true.Для
null: Вызов x.equals(null) всегда должен возвращать false.🟠Предотвращение `NullPointerException`
Если метод
equals() не проверяет, является ли объект null, попытка доступа к его полям или методам вызовет NullPointerException.🚩Как правильно реализовать метод `equals()`?
Вот стандартный способ реализации метода
equals()@Override
public boolean equals(Object obj) {
// Проверяем, равен ли объект null
if (obj == null) {
return false;
}
// Проверяем, является ли объект тем же самым
if (this == obj) {
return true;
}
// Проверяем, принадлежит ли объект тому же классу
if (getClass() != obj.getClass()) {
return false;
}
// Приводим объект к текущему типу
MyClass other = (MyClass) obj;
// Сравниваем необходимые поля
return this.field.equals(other.field);
}
🚩Что происходит, если игнорировать проверку `null`?
Если вы не проверяете
null, код вроде следующего приведет к ошибкеMyClass obj1 = new MyClass("Hello");
MyClass obj2 = null;
System.out.println(obj1.equals(obj2)); // Если нет проверки null -> NullPointerExceptionПример с проверкой
nullclass MyClass {
private String value;
public MyClass(String value) {
this.value = value;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (this == obj) {
return true;
}
if (getClass() != obj.getClass()) {
return false;
}
MyClass other = (MyClass) obj;
return value.equals(other.value);
}
}
public class Main {
public static void main(String[] args) {
MyClass obj1 = new MyClass("Hello");
MyClass obj2 = null;
System.out.println(obj1.equals(obj2)); // false
}
}Ставь 👍 и забирай 📚 Базу знаний
👍3
🤔 В чём разница между HashMap и IdentityHashMap?
- HashMap использует equals() и hashCode() для сравнения;
- IdentityHashMap — использует == и System.identityHashCode().
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
- HashMap использует equals() и hashCode() для сравнения;
- IdentityHashMap — использует == и System.identityHashCode().
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
🔥3👍2🤔2💊1
🤔 В чем разница 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 по умолчанию включает в себя встроенный сервер приложений, что упрощает развертывание и тестирование веб-приложений.
Ставь 👍 и забирай 📚 Базу знаний
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 по умолчанию включает в себя встроенный сервер приложений, что упрощает развертывание и тестирование веб-приложений.
Ставь 👍 и забирай 📚 Базу знаний
👍6
🤔 Какие алгоритмы поиска элемента по массиву известны?
- Линейный поиск (O(n)) — перебор всех элементов;
- Бинарный поиск (O(log n)) — по отсортированному массиву;
- Интерполяционный поиск — улучшение бинарного при равномерном распределении;
- Экспоненциальный поиск — для бесконечных или частично известных массивов.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
- Линейный поиск (O(n)) — перебор всех элементов;
- Бинарный поиск (O(log n)) — по отсортированному массиву;
- Интерполяционный поиск — улучшение бинарного при равномерном распределении;
- Экспоненциальный поиск — для бесконечных или частично известных массивов.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
👍3🔥2
🤔 Что такое as-if-serial semantics?
Обычный код
Что может сделать компилятор?
🚩Что можно менять? (Безопасные оптимизации)
Менять порядок инструкций, если это не влияет на результат.
Удалять лишние переменные и вычисления.
Заменять выражения константами (
Компилятор может поменять местами
🚩Что нельзя менять? (Гарантированный порядок исполнения)
Если поменять порядок
🚩Как `As-If-Serial` влияет на многопоточность?
В многопоточной среде компилятор может менять порядок команд внутри одного потока, но он не знает о другом потоке!
Опасный пример без
Решение –
Ставь 👍 и забирай 📚 Базу знаний
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 и xint 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 для readyvolatile boolean ready = false;
Ставь 👍 и забирай 📚 Базу знаний
👍4
🤔 Что известно про интерфейс Iterable и зачем он нужен?
Iterable<T> — базовый интерфейс, который:
- Позволяет использовать объект в for-each цикле.
- Обязует реализовать метод iterator().
Применяется во всех коллекциях (List, Set, Queue) — он основа для итерации. Без Iterable нельзя использовать for (T t : collection).
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Iterable<T> — базовый интерфейс, который:
- Позволяет использовать объект в for-each цикле.
- Обязует реализовать метод iterator().
Применяется во всех коллекциях (List, Set, Queue) — он основа для итерации. Без Iterable нельзя использовать for (T t : collection).
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
👍4🔥1