2. Через сеттеры или методы (Setter/Method Injection): зависимости устанавливаются через сеттеры или методы после создания объекта.
3. Через поле (Field Injection): зависимости внедряются напрямую в поля с использованием аннотаций, например,
4. Интерфейсное внедрение (Interface Injection): зависимости задаются через методы интерфейса (редко используется).
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🔥1
В Java у каждого потока есть приоритет, но он не гарантирует порядок выполнения.
Java позволяет задавать приоритет потока с помощью метода
setPriority(), который принимает значение от 1 до 10: Thread.MIN_PRIORITY (1) – минимальный приоритет Thread.NORM_PRIORITY (5) – стандартный приоритет (по умолчанию) Thread.MAX_PRIORITY (10) – максимальный приоритет class MyThread extends Thread {
public MyThread(String name, int priority) {
super(name);
setPriority(priority);
}
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(getName() + " выполняется с приоритетом " + getPriority());
}
}
}
public class Main {
public static void main(String[] args) {
MyThread low = new MyThread("Low Priority", Thread.MIN_PRIORITY);
MyThread high = new MyThread("High Priority", Thread.MAX_PRIORITY);
low.start();
high.start();
}
}Приоритет – это всего лишь рекомендация для ОС.
Распределение процессорного времени зависит от планировщика ОС.
В Windows, Linux, macOS приоритеты работают по-разному, и Java не контролирует их на низком уровне.
Реальные способы управления порядком выполнения:
а) Использование
join()Позволяет дождаться выполнения одного потока перед запуском другого.
public class Main {
public static void main(String[] args) throws InterruptedException {
Thread high = new MyThread("High Priority", Thread.MAX_PRIORITY);
Thread low = new MyThread("Low Priority", Thread.MIN_PRIORITY);
high.start();
high.join(); // Ждём, пока high завершится
low.start(); // Теперь запускается low
}
}б) Использование
Executors.newSingleThreadExecutor() Позволяет гарантированно выполнять потоки по очереди.
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Main {
public static void main(String[] args) {
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.submit(() -> System.out.println("Задача 1"));
executor.submit(() -> System.out.println("Задача 2"));
executor.shutdown();
}
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
Я бы убрал XML-конфигурацию в новых проектах — она громоздкая, сложная в поддержке и плохо масштабируется по сравнению с Java-конфигурацией и аннотациями.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
💊22👍1🤔1
Когда у объекта много параметров.
Когда объект трудно создавать через конструктор.
class Car {
private String engine;
private int wheels;
private boolean sunroof;
private Car(CarBuilder builder) {
this.engine = builder.engine;
this.wheels = builder.wheels;
this.sunroof = builder.sunroof;
}
public static class CarBuilder {
private String engine;
private int wheels;
private boolean sunroof;
public CarBuilder setEngine(String engine) {
this.engine = engine;
return this;
}
public CarBuilder setWheels(int wheels) {
this.wheels = wheels;
return this;
}
public CarBuilder setSunroof(boolean sunroof) {
this.sunroof = sunroof;
return this;
}
public Car build() {
return new Car(this);
}
}
}Создаём объект пошагово
Car car = new Car.CarBuilder()
.setEngine("V8")
.setWheels(4)
.setSunroof(true)
.build();
Когда у системы много сложных классов, и вы хотите предоставить один упрощённый интерфейс.
Когда нужно скрыть детали реализации от клиента.
class CPU {
void start() { System.out.println("Процессор запущен."); }
}
class Memory {
void load() { System.out.println("Память загружена."); }
}
class HardDrive {
void read() { System.out.println("Чтение данных с диска."); }
}Создаём
Facade, который скрывает сложность class ComputerFacade {
private CPU cpu;
private Memory memory;
private HardDrive hardDrive;
public ComputerFacade() {
this.cpu = new CPU();
this.memory = new Memory();
this.hardDrive = new HardDrive();
}
public void startComputer() {
cpu.start();
memory.load();
hardDrive.read();
System.out.println("Компьютер включен!");
}
}Теперь клиенту не нужно вызывать кучу методов
ComputerFacade computer = new ComputerFacade();
computer.startComputer(); // Запускает всю систему через 1 метод
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6💊2
- /WEB-INF/ — служебные файлы проекта;
- /WEB-INF/web.xml — дескриптор развертывания;
- /WEB-INF/lib/ — сторонние библиотеки;
- /WEB-INF/classes/ — скомпилированные классы;
- /static/ или /public/ — ресурсы (CSS, JS, изображения).
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
💊14🔥1🤔1
В MySQL (и других реляционных БД) типы данных
DATETIME и TIMESTAMP используются для хранения даты и времени, но у них есть несколько ключевых отличий. Используйте
DATETIME, если: Нужно хранить фиксированное значение даты и времени, не зависящее от часового пояса.
Работаете с датами за пределами 1970-2038 гг.
Требуется удобочитаемый формат (без конверсий).
Используйте
TIMESTAMP, если: Нужно учитывать часовой пояс (например, хранить время в UTC, а при запросе автоматически конвертировать в локальное).
Важно автоматическое обновление при изменении строки (
ON UPDATE CURRENT_TIMESTAMP). Нужно экономить память (занимает в 2 раза меньше места, чем
DATETIME). DATETIME (Фиксированная дата и время)
CREATE TABLE events (
id INT PRIMARY KEY,
event_time DATETIME NOT NULL
);
INSERT INTO events VALUES (1, '2025-02-17 12:30:00');
TIMESTAMP (Автообновление + Часовые пояса)
CREATE TABLE logs (
id INT PRIMARY KEY,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
Если изменим
time_zone, TIMESTAMP отобразится в новом часовом поясе. SET time_zone = 'Europe/Moscow';
SELECT created_at FROM logs;
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
Это метод с реализацией, объявленный внутри интерфейса как static. Он не наследуется и вызывается только через имя интерфейса.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4🔥3
Функциональный интерфейс —это интерфейс, который содержит только один абстрактный метод. Это позволяет использовать лямбда-выражения для создания его анонимных реализаций, делая код более лаконичным и читаемым. Функциональные интерфейсы являются основой для лямбда-выражений и методов ссылок, начиная с версии 8.
Примером этого может служить интерфейс
java.util.function.Predicate<T> который принимает объект типа T и возвращает значение типа boolean. Вот пример использования:Predicate<String> isNotEmpty = s -> !s.isEmpty();
System.out.println(isNotEmpty.test("Hello")); // Выведет true
System.out.println(isNotEmpty.test("")); // Выведет falseЧтобы явно указать, что интерфейс предназначен для использования как функциональный, используется аннотация
@FunctionalInterface. Эта аннотация не обязательна (компилятор может определить функциональный интерфейс и без неё), но она помогает в документировании кода и обеспечивает проверку времени компиляции, гарантируя, что интерфейс содержит только один абстрактный метод.@FunctionalInterface
public interface SimpleFunction {
int apply(int value);
}
// Использование
SimpleFunction triple = value -> value * 3;
System.out.println(triple.apply(5)); // Выведет 15Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
В зависимости от задач, могли использоваться:
- Git, Maven, Gradle, Docker;
- Postman, Swagger — для работы с API;
- IntelliJ IDEA — как IDE;
- Prometheus, Grafana, Kibana — для мониторинга;
- JUnit, Mockito — для тестов;
- SQL — для работы с базами.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
💊5🤔4🔥2👍1
Spring и Spring Boot являются частью экосистемы, которая предоставляет широкий спектр инструментов для разработки современных Java-приложений. Несмотря на тесную связь, между ними есть ключевые отличия.
Это мощный и широко используемый фреймворк для разработки приложений на Java. Он предоставляет обширный набор функциональностей, включая инверсию управления (IoC) и внедрение зависимостей (DI), абстракции для работы с транзакциями, обработку исключений, поддержку аспектно-ориентированного программирования (AOP) и многое другое. Он предназначен для упрощения Java EE разработки, обеспечивая легкость создания масштабируемых и легко поддерживаемых приложений.
С другой стороны, представляет собой расширение Spring Framework, предназначенное для упрощения процесса конфигурации и развертывания Spring-приложений. Он автоматизирует многие процессы, предоставляя "готовые к использованию" настройки для быстрого старта проектов и избавления от необходимости вручную определять стандартную конфигурацию.
Spring Framework предоставляет основу для создания приложений на Java, в то время как Spring Boot предлагает конвенции и автоматическую конфигурацию для быстрого старта и развертывания приложений.
В Spring для настройки приложения часто требуется детальная конфигурация, включая XML-файлы или аннотации. Spring Boot стремится уменьшить эту сложность, автоматически конфигурируя компоненты на основе добавленных в проект зависимостей.
Spring Boot по умолчанию включает в себя встроенный сервер приложений, что упрощает развертывание и тестирование веб-приложений.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
Через имя интерфейса: InterfaceName.methodName(). Такие методы не переопределяются и не доступны через объект класса.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7
Все три аннотации используются в Spring для создания бинов, но у каждой есть своё предназначение.
@Component помечает класс как Spring-бин (компонент). Является универсальной аннотацией.
Можно применять к любым классам, которые должны управляться Spring-контейнером.
@Component
public class MyComponent {
public void doWork() {
System.out.println("Работа компонента");
}
}
@Service – это специализированный @Component, используемый для сервисных классов (логика приложения). Упрощает понимание кода (показывает, что этот класс содержит бизнес-логику).
@Service
public class UserService {
public String getUser() {
return "Пользователь Иван";
}
}
@Repository – это специализированный @Component для слоя доступа к данным (DAO, Repository). Автоматически перехватывает SQL-исключения (
PersistenceExceptionTranslationPostProcessor) и преобразует их в DataAccessException. @Repository
public class UserRepository {
public String findUserById(int id) {
return "Пользователь с ID " + id;
}
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12
Для этого используют первичный ключ (Primary Key) — уникальное поле или набор полей.
Это может быть AUTO_INCREMENT, UUID или вручную заданное значение. Он позволяет однозначно идентифицировать строку в таблице.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7
Garbage Collector (GC) в Java начинает сборку мусора, когда объекты в памяти больше не используются и не имеют активных ссылок.
GC понимает, что объект можно удалить, если на него больше не ссылается ни одна переменная или он стал недостижимым.
class Demo {
int value;
}
public class Main {
public static void main(String[] args) {
Demo obj = new Demo(); // Создан объект в памяти (Heap)
obj = null; // Теперь на него нет ссылки → GC его удалит
}
}Если в куче (Heap) осталось мало свободной памяти, JVM может запустить GC.
GC в Java автоматический, и его запуск зависит от алгоритма сборщика мусора. Некоторые из них:
Serial GC (для маленьких программ)
Parallel GC (по умолчанию в Java 8)
G1 GC (по умолчанию в Java 11+)
ZGC, Shenandoah GC (для высоконагруженных систем)
Устарело, потому что не умеет работать с циклическими ссылками.
Основной метод, который использует GC в Java.
GC начинает с корневых объектов (GC Roots) и проверяет, какие объекты достижимы.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Коллекция
HashMap не является потокобезопасной. Это означает, что при одновременном доступе к нему из нескольких потоков без должной синхронизации могут возникнуть проблемы, такие как потеря данных, гонки за данные и другие виды состояний гонки. Если один поток изменяет ее структуру (например, добавляя или удаляя элементы), в то время как другой поток итерирует по ней или также пытается внести изменения, результаты могут быть непредсказуемыми.Collections.synchronizedMap(Map)Оборачивает ее (или любую другую карту) в потокобезопасную обёртку, гарантируя безопасность при доступе из разных потоков. Однако при использовании этого метода важно помнить, что если итерация по коллекции происходит в многопоточной среде, необходимо синхронизировать весь блок итерации на возвращённой карте для предотвращения конкурентных модификаций.
Map<String, String> map = Collections.synchronizedMap(new HashMap<>());
ConcurrentHashMapПредоставляет потокобезопасную реализацию карты без блокировки всей карты.
ConcurrentHashMap разработан для высокой конкуренции и эффективности при доступе из множества потоков, обеспечивая лучшую производительность по сравнению с synchronizedMap. ConcurrentHashMap позволяет одновременно читать данные из карты несколькими потоками без блокировки и записывать данные при минимальной блокировке.Map<String, String> concurrentMap = new ConcurrentHashMap<>();
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Хранимая процедура — это набор SQL-команд, сохранённых в базе данных.
Вызов через JDBC выполняется через CallableStatement, например:
CallableStatement cs = connection.prepareCall("{call my_procedure(?)}");.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
Синхронизация — это механизм, который используется для контроля доступа к общим ресурсам или критическим секциям кода в среде, где несколько потоков или процессов могут одновременно выполняться. Основная цель — обеспечить корректное взаимодействие между потоками, предотвращая одновременное выполнение определённых участков кода, которые могут привести к конфликтам или неконсистентному состоянию данных.
Гонка данных возникает, когда два или более потоков одновременно пытаются изменить общие данные, и результат выполнения зависит от того, в каком порядке потоки выполняют операции. Синхронизация помогает управлять доступом к данным таким образом, чтобы обеспечить их целостность.
В многопоточной среде изменения, сделанные одним потоком в общем ресурсе, могут не быть сразу видны другим потокам из-за кэширования данных в процессорах или оптимизаций компилятора. Синхронизация гарантирует, что изменения, сделанные одним потоком, будут корректно видны другим потокам.
Некоторые операции или ресурсы требуют последовательного доступа для предотвращения конфликтов или некорректной работы. Например, запись в файл или обновление базы данных должны выполняться последовательно, чтобы избежать наложения данных или повреждения структуры данных.
synchronizedМожет использоваться для блокировки целого метода или определённого блока кода, обеспечивая монопольный доступ к этому участку кода для одного потока одновременно.
java.util.concurrent.locksПредоставляют более гибкие возможности для управления блокировками, включая попытку захвата блокировки без ожидания, захват прерываемых блокировок и блокировки с возможностью повторного входа.
volatile)Обеспечивают видимость изменений переменных между разными потоками, но не контролируют последовательность доступа к переменной.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
- Простота и гибкость;
- Разделение на шаблон/логика/стили в одном файле (.vue);
- Сильная поддержка компонентов;
- Реактивные данные и computed свойства;
- Хорошая поддержка SSR и сборщиков (Vite, Webpack).
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
💊20
Каждый бин (компонент) проходит через жизненный цикл, который начинается с его создания и заканчивается уничтожением. Этот цикл включает в себя ряд этапов, на которых он предоставляет различные точки для настройки поведения бина. Вот основные этапы жизненного цикла:
Создает экземпляр бина из класса определения бина.
Внедряет значения и ссылки на другие бины в свойства текущего бина, используя конфигурацию, заданную в XML, аннотациях или конфигурации.
Если бин реализует один из Aware интерфейсов, он вызывает соответствующие методы, передавая экземпляру бина ссылку на контекст, фабрику бинов и т.д.
Перед инициализацией бина, он дает возможность BeanPostProcessor'ам обработать объект. Это может быть использовано для проксирования бинов или для иной предварительной обработки.
Если для бина определен метод инициализации (через аннотацию
@PostConstruct, интерфейс InitializingBean или атрибут init-method в XML-конфигурации), он вызывает его после того, как все свойства бина были установлены.После вызова метода инициализации бин полностью инициализирован и готов к использованию в приложении.
Когда контекст приложения закрывается, и бины должны быть уничтожены, он вызывает метод уничтожения для бинов, которые определяют его (через аннотацию
@PreDestroy, интерфейс DisposableBean или атрибут destroy-method в XML-конфигурации).Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥5👍3
Для подключения своей библиотеки:
- собрать её в JAR;
- опубликовать в локальный или удалённый репозиторий (например, Maven Central, Nexus, Artifactory);
- добавить зависимость в pom.xml или build.gradle другого проекта.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14🔥1