2. Упрощение разработки: Позволяет сочетать HTML и Java-код, облегчая создание веб-приложений.
3. Интеграция с Java EE: Позволяет работать с сервлетами и серверной логикой.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6💊6
Spring – это мощный фреймворк для разработки Java-приложений, который упрощает работу с бэкендом, базами данных и веб-сервисами.
Самый быстрый способ – использовать [Spring Initializr](https://start.spring.io/).
Заходим на [start.spring.io](https://start.spring.io/)
Выбираем:
Maven / Gradle
Java 17+
Spring Boot 3+
Зависимости: Spring Web, Spring Data JPA, PostgreSQL/MySQL (если нужна БД)
Скачиваем и открываем в IntelliJ IDEA или VS Code.
<dependencies>
<!-- Spring Boot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Boot JPA + Hibernate -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- Драйвер для PostgreSQL -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>
<!-- Lombok (автоматически генерирует геттеры/сеттеры) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
Контроллер обрабатывает HTTP-запросы (
GET, POST, PUT, DELETE). @RestController
@RequestMapping("/hello")
public class HelloController {
@GetMapping
public String sayHello() {
return "Привет, Spring!";
}
}
Запрос в браузере
http://localhost:8080/hello
Ответ
Привет, Spring!
Сервисы обрабатывают данные и реализуют бизнес-логику.
@Service
public class UserService {
public String getUserGreeting(String name) {
return "Привет, " + name + "!";
}
}
Использование сервиса в контроллере
@RestController
@RequestMapping("/user")
public class UserController {
private final UserService userService;
@Autowired // Внедрение зависимости
public UserController(UserService userService) {
this.userService = userService;
}
@GetMapping("/{name}")
public String getUserGreeting(@PathVariable String name) {
return userService.getUserGreeting(name);
}
}
Запрос в браузере:
http://localhost:8080/user/Иван
Ответ
Привет, Иван!
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
В Java доступны следующие логические операторы:
- && — логическое И (и левое, и правое выражение должны быть истинными).
- || — логическое ИЛИ (достаточно, чтобы одно было истинным).
- ! — логическое отрицание (инвертирует значение true <-> false).
- ^ — исключающее ИЛИ (XOR): результат true, если только одно из значений true.
Используются для построения условий в if, while, for и других конструкциях.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12
Парадигма программирования определяет способ мышления и подход к написанию кода. В зависимости от выбранной парадигмы, в центре может стоять разное ключевое понятие.
Код строится вокруг последовательности инструкций.
Данные изменяются с помощью вызова функций (процедур).
Пример: C, Pascal.
int sum(int a, int b) {
return a + b;
}
int main() {
int result = sum(5, 3);
printf("%d", result);
return 0;
}Мир представляется в виде объектов, у которых есть состояние (поля) и поведение (методы).
Используются принципы: инкапсуляция, наследование, полиморфизм.
Пример: Java, C++, Python.
class Car {
private String model;
public Car(String model) {
this.model = model;
}
public void drive() {
System.out.println(model + " едет!");
}
}
public class Main {
public static void main(String[] args) {
Car car = new Car("Tesla");
car.drive(); // Tesla едет!
}
}Использование чистых функций (без изменения состояния).
Избегание побочных эффектов и мутабельности.
Пример: Haskell, Scala, Kotlin, Java (Stream API).
import java.util.List;
public class Main {
public static void main(String[] args) {
List<Integer> numbers = List.of(1, 2, 3, 4, 5);
numbers.stream()
.map(n -> n * 2) // Умножаем каждый элемент на 2
.forEach(System.out::println); // Вывод результата
}
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11
Нужно создать новый класс, который наследует Exception (для checked) или RuntimeException (для unchecked). Обычно добавляют конструкторы с сообщением и/или причиной.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9
Spring Bean – это ОБЪЕКТ, который управляется Spring-контейнером.
Обычный класс (НЕ Bean)
class Car {
void drive() {
System.out.println("Машина едет...");
}
}public class Main {
public static void main(String[] args) {
Car car = new Car(); // Создание обычного объекта вручную
car.drive();
}
}Bean в Spring
import org.springframework.stereotype.Component;
@Component // Аннотация говорит Spring, что этот класс – Bean
class Car {
void drive() {
System.out.println("Spring-машина едет...");
}
}
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); // Получаем объект из Spring-контейнера
car.drive();
}
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9🔥3💊1
- ООП — работает с объектами, состоянием, поведением.
- Процедурное — работает с функциями и структурами, где данные и логика отдельно.
Технически:
- В ООП — данные и поведение связаны.
- В процедурном — функции вызываются по необходимости, без связи с объектами.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11
Это принцип объектно-ориентированного программирования (ООП), который скрывает детали реализации объекта и показывает только его наиболее важные характеристики. Она позволяет сосредоточиться на сущности объекта, игнорируя его внутреннюю сложность.
В Java абстракция достигается через:
Абстрактные классы
Интерфейсы
Абстрактный класс — это класс, который не может быть создан напрямую, но может содержать:
Абстрактные методы (без реализации, только сигнатуры);
Обычные методы (с реализацией).
Используется, если вы хотите описать общее поведение для группы классов, но часть поведения оставить на усмотрение конкретных подклассов.
abstract class Animal {
// Абстрактный метод — реализуется в подклассах
abstract void makeSound();
// Обычный метод
void eat() {
System.out.println("This animal eats food.");
}
}
class Dog extends Animal {
@Override
void makeSound() {
System.out.println("Woof!");
}
}
class Cat extends Animal {
@Override
void makeSound() {
System.out.println("Meow!");
}
}
public class Main {
public static void main(String[] args) {
Animal dog = new Dog();
dog.makeSound(); // Woof!
dog.eat(); // This animal eats food.
Animal cat = new Cat();
cat.makeSound(); // Meow!
}
}Интерфейс — это чистый контракт, который определяет набор методов, которые класс должен реализовать.
В отличие от абстрактного класса:
Интерфейс не может содержать полей (кроме
static final).Класс может реализовать несколько интерфейсов (множественное наследование).
interface Vehicle {
void start(); // метод без реализации
void stop();
}
class Car implements Vehicle {
@Override
public void start() {
System.out.println("Car is starting.");
}
@Override
public void stop() {
System.out.println("Car is stopping.");
}
}
class Bike implements Vehicle {
@Override
public void start() {
System.out.println("Bike is starting.");
}
@Override
public void stop() {
System.out.println("Bike is stopping.");
}
}
public class Main {
public static void main(String[] args) {
Vehicle car = new Car();
car.start(); // Car is starting.
car.stop(); // Car is stopping.
Vehicle bike = new Bike();
bike.start(); // Bike is starting.
bike.stop(); // Bike is stopping.
}
}Программистам не нужно знать все детали реализации объекта. Они работают только с его интерфейсом.
Код становится понятным и модульным, так как мы сосредоточиваемся на важной логике.
Абстракция позволяет использовать один и тот же код для разных объектов.
Если нужно изменить реализацию, это не затронет остальную часть программы (если она работает через абстрактный контракт).
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4🤔1💊1
- Один объект — Node<K,V> или TreeNode<K,V>;
- Плюс, возможно, перехеширование (новый массив), если достигнут порог загрузки (load factor).
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥5💊4👍2
В Java потоки управляются объектами класса
Thread, и каждый поток выполняет одну последовательность инструкций. Минимальная рабочая единица – это один поток выполнения, который работает независимо от других.Самый простой способ создать поток – использовать класс
Thread:Thread thread = new Thread(() -> System.out.println("Привет из потока!"));
thread.start();Можно создать поток, передав задачу в
Runnable:Runnable task = () -> System.out.println("Работает поток!");
Thread thread = new Thread(task);
thread.start();Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3💊1
Dirty Checking — механизм, при котором Hibernate:
- отслеживает изменения в объектах после их загрузки;
- автоматически формирует UPDATE только для изменённых полей при коммите транзакции.
Это экономит запросы и повышает производительность.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥9👍2
Параметры инициализации могут быть настроены через файл конфигурации
web.xml или с помощью аннотаций в сервлетах. Могут быть настроены для всего веб-приложения или для конкретных сервлетов и страниц.web.xmlМожно настроить в разделе
<servlet> элемента конфигурационного файла web.xml.<web-app>
<servlet>
<servlet-name>ExampleServlet</servlet-name>
<jsp-file>/example.jsp</jsp-file>
<init-param>
<param-name>param1</param-name>
<param-value>value1</param-value>
</init-param>
<init-param>
<param-name>param2</param-name>
<param-value>value2</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>ExampleServlet</servlet-name>
<url-pattern>/example</url-pattern>
</servlet-mapping>
</web-app>
Доступ к параметрам инициализации в JSP можно получить через объект
config в JSP.<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<noscript>Initialization Parameters Example</noscript>
</head>
<body>
<h1>Initialization Parameters Example</h1>
<%
// Получение параметров инициализации
String param1 = config.getInitParameter("param1");
String param2 = config.getInitParameter("param2");
%>
<p>Param1: <%= param1 %></p>
<p>Param2: <%= param2 %></p>
</body>
</html>
Можно настроить в разделе
<context-param> элемента конфигурационного файла web.xml.<web-app>
<context-param>
<param-name>globalParam1</param-name>
<param-value>globalValue1</param-value>
</context-param>
<context-param>
<param-name>globalParam2</param-name>
<param-value>globalValue2</param-value>
</context-param>
</web-app>
Доступ к параметрам инициализации для всего приложения можно получить через объект
ServletContext.<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<noscript>Global Initialization Parameters Example</noscript>
</head>
<body>
<h1>Global Initialization Parameters Example</h1>
<%
// Получение глобальных параметров инициализации
String globalParam1 = application.getInitParameter("globalParam1");
String globalParam2 = application.getInitParameter("globalParam2");
%>
<p>Global Param1: <%= globalParam1 %></p>
<p>Global Param2: <%= globalParam2 %></p>
</body>
</html>
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4💊4🔥1
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍13
В Java строки (
String) являются неизменяемыми (immutable) объектами и обрабатываются особым образом, особенно при их создании.Когда вы пишете:
String str1 = "Hello";
Когда вы создаёте строку так:
String str2 = new String("Hello");public class StringTest {
public static void main(String[] args) {
String str1 = "Hello";
String str2 = "Hello";
String str3 = new String("Hello");
System.out.println(str1 == str2); // true (ссылаются на один объект в пуле)
System.out.println(str1 == str3); // false (разные объекты в памяти)
System.out.println(str1.equals(str3)); // true (содержимое одинаковое)
}
}В 99% случаев
new String() не нужен. Его создание расходует память и снижает производительность.Но он может быть полезен, если вы намеренно хотите создать новый объект, например, для защиты от изменения ссылок:
String safeCopy = new String(originalString); // Теперь это точно отдельный объект
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10🤔4
Объекты, созданные с помощью new, хранятся в куче (Heap) — это основная область памяти, управляемая сборщиком мусора. Ссылки на них могут храниться в стеке, если это локальные переменные метода.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍17
Да, лямбда-выражения являются важной частью современной разработки на Java, и я активно их использую в своей работе. Лямбда-выражения помогают писать более лаконичный и выразительный код, особенно при работе с коллекциями и потоками данных. Вот несколько распространенных случаев использования лямбда-выражений в Java:
Использование лямбда-выражений с методом
forEach позволяет компактно и удобно итерировать по элементам коллекций. List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.forEach(name -> System.out.println(name));С использованием Stream API и лямбда-выражений можно легко фильтровать, сортировать и преобразовывать коллекции.
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");
List<String> filteredNames = names.stream()
.filter(name -> name.startsWith("A"))
.collect(Collectors.toList());
filteredNames.forEach(System.out::println); // Вывод: AliceЛямбда-выражения упрощают сортировку коллекций с использованием метода
sort. List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.sort((name1, name2) -> name1.compareTo(name2));
names.forEach(System.out::println);Лямбда-выражения широко используются с функциональными интерфейсами, такими как
Predicate, Function, Consumer и Supplier. // Predicate
Predicate<String> startsWithA = s -> s.startsWith("A");
boolean result = startsWithA.test("Alice"); // true
// Function
Function<String, Integer> lengthFunction = s -> s.length();
int length = lengthFunction.apply("Hello"); // 5
// Consumer
Consumer<String> printConsumer = s -> System.out.println(s);
printConsumer.accept("Hello, World!"); // Вывод: Hello, World!
// Supplier
Supplier<String> stringSupplier = () -> "Hello, Supplier!";
String suppliedString = stringSupplier.get();
System.out.println(suppliedString); // Вывод: Hello, Supplier!
Лямбда-выражения с использованием параллельных потоков позволяют легко выполнять параллельные вычисления.
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.parallelStream()
.mapToInt(Integer::intValue)
.sum();
System.out.println("Sum: " + sum); // Вывод: Sum: 15
Предположим, у нас есть список сотрудников, и мы хотим отфильтровать и отсортировать их по имени.
import java.util.*;
import java.util.stream.Collectors;
class Employee {
private String name;
private int age;
public Employee(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
@Override
public String toString() {
return "Employee{name='" + name + "', age=" + age + '}';
}
}
public class LambdaExample {
public static void main(String[] args) {
List<Employee> employees = Arrays.asList(
new Employee("Alice", 30),
new Employee("Bob", 25),
new Employee("Charlie", 35),
new Employee("David", 28)
);
// Фильтрация и сортировка сотрудников по имени
List<Employee> filteredAndSorted = employees.stream()
.filter(e -> e.getAge() > 27)
.sorted(Comparator.comparing(Employee::getName))
.collect(Collectors.toList());
filteredAndSorted.forEach(System.out::println);
}
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8💊1
Сокрытие метода (method hiding) происходит, когда:
- Подкласс определяет статический метод с такой же сигнатурой, как у суперкласса.
- Но это не переопределение — статические методы не полиморфны.
В этом случае вызывается метод по типу ссылки, а не объекта.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥10👍2
В интерфейсе могут располагаться различные типы методов, начиная с Java 8, когда в язык были добавлены новые возможности, такие как default методы и static методы. До Java 8 интерфейсы могли содержать только абстрактные методы. Ниже представлены типы методов, которые могут быть объявлены в интерфейсе:
Это методы без тела, предназначенные для переопределения в классах, которые реализуют интерфейс. Абстрактные методы представляют собой контракт, который должен быть выполнен классом-реализатором. Все методы в интерфейсе неявно являются
public abstract, даже если явно не указаны эти модификаторы.void myMethod();
Позволяют определять реализацию метода непосредственно в интерфейсе. Классы, реализующие интерфейс, могут переопределять эти методы, но это не обязательно. Default методы были введены для обеспечения обратной совместимости, позволяя добавлять новые методы в интерфейсы без нарушения существующих реализаций.
default void defaultMethod() {
// Реализация
}Позволяют определять методы с реализацией, которые могут быть вызваны без создания экземпляра класса, реализующего интерфейс. Эти методы нельзя переопределить в реализующем интерфейс классе.
static void staticMethod() {
// Реализация
}Позволяют определять вспомогательные методы, которые предназначены для использования в default или static методах внутри того же интерфейса. Эти методы не могут быть вызваны извне интерфейса или реализующих его классов.
private void privateMethod() {
// Реализация
}Пример
public interface MyInterface {
// Абстрактный метод
void abstractMethod();
// Default метод
default void defaultMethod() {
System.out.println("Default implementation");
}
// Static метод
static void staticMethod() {
System.out.println("Static implementation");
}
// Private метод (используется внутри интерфейса)
private void privateMethod() {
System.out.println("Private helper method");
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14
- Использует хеш-таблицу (HashMap), дерево (TreeMap) или список (LinkedHashMap) в зависимости от реализации.
- Хранит пары ключ — значение, и не допускает дубликатов ключей.
- Доступ, вставка, удаление — происходят через методы put, get, remove.
Также в Map доступны представления:
- keySet() — множество ключей;
- values() — коллекция значений;
- entrySet() — пары ключ-значение.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9🔥2
В Java стандартные коллекции из
java.util (например, ArrayList, HashMap, HashSet) не потокобезопасны. Чтобы использовать их в многопоточной среде, можно применять синхронизированные обёртки** и **коллекции из java.util.concurrent. Java предоставляет методы для создания потокобезопасных обёрток над обычными коллекциями:
import java.util.*;
public class SynchronizedCollectionsExample {
public static void main(String[] args) {
List<Integer> syncList = Collections.synchronizedList(new ArrayList<>());
Map<String, String> syncMap = Collections.synchronizedMap(new HashMap<>());
Set<Integer> syncSet = Collections.synchronizedSet(new HashSet<>());
syncList.add(1);
syncMap.put("key", "value");
syncSet.add(10);
}
}
Даже если коллекция синхронизирована, её итерация не потокобезопасна.
for (Integer num : syncList) { // Возможен ConcurrentModificationException!
System.out.println(num);
}Чтобы избежать ошибок, итерацию нужно делать внутри
synchronized блокаsynchronized (syncList) {
for (Integer num : syncList) {
System.out.println(num);
}
}Вместо
Collections.synchronizedXXX() лучше использовать современные конкурентные коллекции из java.util.concurrent. Они спроектированы для многопоточности и работают быстрее. import java.util.concurrent.*;
public class ConcurrentMapExample {
public static void main(String[] args) {
ConcurrentMap<String, Integer> concurrentMap = new ConcurrentHashMap<>();
concurrentMap.put("one", 1);
concurrentMap.put("two", 2);
System.out.println(concurrentMap.get("one")); // 1
}
}
Пример
CopyOnWriteArrayList (потокобезопасный список, работающий через копии)import java.util.concurrent.CopyOnWriteArrayList;
public class CopyOnWriteExample {
public static void main(String[] args) {
CopyOnWriteArrayList<Integer> list = new CopyOnWriteArrayList<>();
list.add(1);
list.add(2);
for (Integer num : list) { // Без ConcurrentModificationException!
System.out.println(num);
}
}
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5🔥3
- Реализовать интерфейс Serializable, но выбрасывать исключение в методах сериализации;
- Либо просто не реализовывать интерфейс Serializable (в случае стандартной Java сериализации).
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥4💊4👍2