Java: примеры кода, интересные фишки и полезные трюки
Купить рекламу: https://telega.in/c/java_tips_and_tricks
✍️По всем вопросам: @Pascal4eg
Информация о канале обновлена 18.11.2025.
Java: примеры кода, интересные фишки и полезные трюки
Купить рекламу: https://telega.in/c/java_tips_and_tricks
✍️По всем вопросам: @Pascal4eg
🧩 Java без сюрпризов: контрактное тестирование между сервисами
Когда микросервисы растут, как грибы после дождя — баги начинают путешествовать между ними.
Контрактное тестирование ставит границы: продюсер не ломает клиента, а потребитель не ждёт несуществующие поля.
Schema-first и consumer-driven подходы делают интеграцию предсказуемой — без ручных костылей.
⚙️ 1. Schema-first — один источник истины
syntax = "proto3";
message Order {
string id = 1;
double amount = 2;
string status = 3;
}
✅ Сначала схема (OpenAPI, Avro, Protobuf) — потом код. Никаких сюрпризов при интеграции.
🚀 2. Генерация классов из схемы
mvn protobuf:compile
➡️ Java-классы создаются из схемы автоматически — никто не пишет руками DTO.
🧠 3. Контракты между командами
interaction:
request:
method: GET
path: /orders/123
response:
status: 200
body:
id: "123"
amount: 50.0
✅ Фиксируешь поведение API. Если кто-то меняет ответ — тесты падают.
🧩 4. Consumer-driven contracts через Pact
@Pact(consumer = "billing-service")
public RequestResponsePact pact(PactDslWithProvider builder) {
return builder
.given("Order exists")
.uponReceiving("Get order by ID")
.path("/orders/123").method("GET")
.willRespondWith()
.status(200)
.body("{\"id\":\"123\",\"amount\":50.0}")
.toPact();
}
✅ Потребитель диктует контракт — продюсер обязан его выполнить.
🔍 5. Проверка продюсера
@Provider("order-service")
@PactFolder("pacts")
public class ProviderVerificationTest {
@TestTemplate
@ExtendWith(PactVerificationInvocationContextProvider.class)
void verifyPacts(PactVerificationContext context) {
context.verifyInteraction();
}
}
✅ Перед деплоем проверяется, не сломали ли API.
⚙️ 6. Pact Broker — как единая база контрактов
docker run -d -p 9292:9292 pactfoundation/pact-broker
➡️ Все контракты хранятся централизованно, CI проверяет совместимость.
🧩 7. Валидация схемы при CI
mvn verify -Pcontract-tests
✅ Любая несовместимая правка схемы — стоп-релиз.
🧱 8. Миграция без боли
body:
amount: 50.0
currency: "USD" # новое поле, не ломает старый контракт
➡️ Добавляй поля безопасно: старые клиенты не страдают.
📦 9. Интеграция с Spring Cloud Contract
@SpringBootTest
@AutoConfigureStubRunner(ids = "com.demo:order-service:+:stubs:8080")
class BillingTest { ... }
✅ Потребитель тестируется на реальных стабах продюсера.
🗣 Запомни: контрактное тестирование — это страховка от хаоса. Код может меняться, но правила общения — нет.
⌨️ PriorityQueue — это реализация структуры данных очередь с приоритетом, которая упорядочивает элементы по их естественному порядку или по заданному компаратору. Она представляет собой часть коллекции Java Collections Framework и находится в пакете java.util.
В отличие от Queue, элементы PriorityQueue не упорядочены по времени их добавления, а по приоритету.
Основные методы:
add(E e) - добавляет элемент в очередь.
remove() - удаляет и возвращает элемент с наивысшим приоритетом. Если очередь пуста, генерируется исключение NoSuchElementException.
poll() - удаляет и возвращает элемент с наивысшим приоритетом. Если очередь пуста, возвращает null.
peek() - возвращает, но не удаляет элемент с наивысшим приоритетом. Если очередь пуста, возвращает null.
element() - возвращает, но не удаляет элемент с наивысшим приоритетом. Если очередь пуста, генерируется исключение NoSuchElementException.
Пример:
class Task implements Comparable{
String name;
Integer priority;
public Task(String name, Integer priority) {
this.name = name;
this.priority = priority;
}
@Override
public int compareTo(@NotNull Task o) {
return priority - o.priority;
}
}
public class Test {
public static void main(String[] args) {
PriorityQueuepq = new PriorityQueue();
pq.add(new Task("Task1", 1));
pq.add(new Task("Task5", 5));
pq.add(new Task("Task2", 2));
pq.add(new Task("Task4", 4));
pq.add(new Task("Task3", 3));
while (!pq.isEmpty()) {
System.out.println(pq.poll().name);
// Выведет: Task1, Task2, Task3, Task4, Task5
}
}
}
#java #PriorityQueue
⌨️ private методы в интерфейсах
В Java с версии 9 появилась возможность использовать private методы в интерфейсах. Эти методы предназначены для улучшения внутренней организации интерфейсов, позволяя избежать дублирования кода в default и static методах. private методы помогают реализовать общую логику, к которой могут обращаться другие методы интерфейса, но они остаются недоступными для классов, реализующих интерфейс.
private методы могут быть как экземплярными, так и static.
Пример:
public interface MyInterface {
default void showMessage() {
print("Default method calling private method");
}
static void showStaticMessage() {
print("Static method calling private method");
}
// Private method for reuse
private static void print(String message) {
System.out.println(message);
}
}
#java #interface #private
Все операции Stream делятся на промежуточные и терминальные и объединяются в потоковые конвейеры.
Потоковый конвейер состоит из источника (например, коллекции, массива, функции-генератора, канала ввода-вывода или генератора бесконечной последовательности) за которым следует ноль или более промежуточных операций и терминальной операции.
Промежуточные операции
📌 Промежуточные операции не выполняются до тех пор, пока не будет вызвана какая-либо терминальная операция.
Они составляют конвейер выполнения Stream. Промежуточную операцию можно добавить в конвейер Stream методами:
filter()
map()
flatMap()
distinct()
sorted()
peek()
limit()
skip()
Все промежуточные операции являются ленивыми, поэтому они не выполняются до тех пор, пока результат обработки действительно не понадобится.
По сути, промежуточные операции возвращают новый поток. Выполнение промежуточной операции фактически не выполняет никакой операции, а вместо этого создает новый поток, который при прохождении содержит элементы исходного потока, соответствующие данному предикату.
Таким образом, обход потока не начинается до тех пор, пока не будет выполнена терминальная операция конвейера.
Это очень важное свойство, особенно важное для бесконечных потоков, поскольку оно позволяет нам создавать потоки, которые будут фактически вызываться только при вызове терминальной операции.
Терминальные операции
Терминальные операции могут проходить через поток для получения результата или побочного эффекта.
📌 После выполнения терминальной операции, потоковый конвейер считается использованным и больше не может использоваться.
Терминальные операции:
forEach()
forEachOrdered()
toArray()
reduce()
collect()
min()
max()
count()
anyMatch()
allMatch()
noneMatch()
findFirst()
findAny()
Каждая из этих операций инициирует выполнение всех промежуточных операций.
⌨️ Внутренняя реализация ArrayList
ArrayList — это реализация динамического массива из стандартной библиотеки коллекций java.util. Он представляет собой список, который может изменять свой размер в зависимости от количества добавляемых элементов.
ArrayList основан на массиве объектов. Это означает, что под капотом у него есть массив фиксированного размера. Когда этот массив заполняется, создается новый массив большего размера, в который копируются элементы старого массива, а затем старый массив удаляется.
Размер и емкость
✔️ Размер (size) — это количество элементов, которые фактически содержатся в ArrayList.
✔️ Емкость (capacity) — это текущий размер внутреннего массива. Когда количество элементов превышает емкость, массив расширяется.
Когда ArrayList инициализируется, его емкость по умолчанию равна 10. Если количество элементов в массиве превышает емкость, массив автоматически увеличивается. Обычно емкость увеличивается по формуле: новая емкость = старая емкость * 1.5.
Для удаления элементов используется метод remove(int index). После удаления элемента все элементы, находящиеся справа от удаленного, смещаются на одну позицию влево, что требует временных затрат O(n).
После удаления элементов ArrayList не автоматически уменьшает емкость внутреннего массива, то есть массив может занимать больше памяти, чем требуется для хранения фактических элементов. Однако для оптимизации можно вручную уменьшить емкость до текущего размера с помощью метода trimToSize().
Одним из преимуществ ArrayList является возможность доступа к элементам по индексу за время O(1). Это возможно благодаря тому, что элементы хранятся в массиве, и доступ к ним осуществляется через индекс.
#java #ArrayList
🌐 REST и RESTful API
REST (Representational State Transfer) — это архитектурный стиль для проектирования сетевых приложений. Он использует стандартные методы HTTP и акцентирует внимание на взаимодействии между клиентом и сервером с помощью ресурсов.
Основные принципы REST:
1️⃣ Клиент-серверная архитектура:
- Четкое разделение между клиентом и сервером. Клиент отвечает за пользовательский интерфейс, а сервер — за обработку данных и бизнес-логику.
2️⃣ Статус и состояние:
- Каждый запрос от клиента к серверу должен содержать всю необходимую информацию для обработки запроса. Сервер не хранит состояние сеанса (stateless).
3️⃣ Кэшируемость:
- Ответы должны быть явно обнародованы как кэшируемые или не кэшируемые. Это позволяет уменьшить количество запросов к серверу и улучшает производительность.
4️⃣ Единообразие интерфейса:
- Все взаимодействия между клиентом и сервером осуществляются через четкий и единообразный интерфейс, что упрощает интеграцию.
5️⃣ Многоуровневость:
- Система может быть структурирована на несколько уровней, где каждый уровень может вызывать другой, обеспечивая гибкость и упрощая управление.
RESTful API — это API, который следует принципам REST. Это интерфейс, который использует стандартные HTTP методы для выполнения операций с ресурсами, представленными в виде URI.
Основные HTTP методы в RESTful API:
1️⃣ GET:
- Используется для получения информации о ресурсе.
- Пример: GET /users — получить список всех пользователей.
2️⃣ POST:
- Используется для создания нового ресурса.
- Пример: POST /users — создать нового пользователя.
3️⃣ PUT:
- Используется для обновления существующего ресурса (полное обновление).
- Пример: PUT /users/1 — обновить информацию о пользователе с ID=1.
4️⃣ PATCH:
- Используется для частичного обновления ресурса.
- Пример: PATCH /users/1 — обновить определенные поля у пользователя с ID=1.
5️⃣ DELETE:
- Используется для удаления ресурса.
- Пример: DELETE /users/1 — удалить пользователя с ID=1.
RESTful API обычно возвращают данные в форматах:
- JSON (JavaScript Object Notation): легковесный формат, который легко читаем и записывается как людьми, так и машинами. Это самый распространенный формат для передачи данных в RESTful API.
- XML (eXtensible Markup Language): более старый формат, который также используется, но менее популярен в новых приложениях.
Применение RESTful API:
✔️ Веб-приложения: RESTful API часто используются в веб-приложениях для взаимодействия с серверами и базами данных.
✔️ Мобильные приложения: Многие мобильные приложения используют RESTful API для получения данных.
✔️ Интеграция систем: RESTful API позволяют различным системам взаимодействовать друг с другом с минимальными усилиями.
#REST #RESTfulAPI #API
В этом видео автор анализирует, насколько Java остаётся актуальной в 2025 году и какие изменения произошли в языке и экосистеме.
Разбираются ключевые области применения Java — от корпоративных систем и Android-разработки до backend-сервисов — и сравнивается её востребованность с другими языками программирования.
чник
??️Запомни: Java не те
🤩 Java Фишки и трюки || #Видео
Владелец канала не предоставил расширенную статистику, но Вы можете сделать ему запрос на ее получение.
Также Вы можете воспользоваться расширенным поиском и отфильтровать результаты по каналам, которые предоставили расширенную статистику.
Также Вы можете воспользоваться расширенным поиском и отфильтровать результаты по каналам, которые предоставили расширенную статистику.
Подтвердите, что вы не робот
Вы выполнили несколько запросов, и прежде чем продолжить, мы ходим убелиться в том, что они не автоматизированные.
Наш сайт использует cookie-файлы, чтобы сделать сервисы быстрее и удобнее.
Продолжая им пользоваться, вы принимаете условия
Пользовательского соглашения
и соглашаетесь со сбором cookie-файлов.
Подробности про обработку данных — в нашей
Политике обработки персональных данных.