Java for Beginner
673 subscribers
541 photos
155 videos
12 files
827 links
Канал от новичков для новичков!
Изучайте Java вместе с нами!
Здесь мы обмениваемся опытом и постоянно изучаем что-то новое!

Наш YouTube канал - https://www.youtube.com/@Java_Beginner-Dev

Наш канал на RUTube - https://rutube.ru/channel/37896292/
Download Telegram
Выбираем темы предложенные на этой неделе!
Anonymous Poll
31%
JavaMailSender
14%
AOP
20%
IO/NIO
20%
Maven
14%
JSON
Встреча создана!

https://telemost.yandex.ru/j/93539195233421

Залетаем! ✈️
Please open Telegram to view this post
VIEW IN TELEGRAM
Многопоточка во всей красе. Часть 1.

Встреча от 01.06.2025

Запись встречи -
YOUTUBE
RUTUBE

На сегодняшней встрече @rKiraLis39 (огромное спасибо ему 👏) начал рассказывать нам о многопоточке.

Что мы узнали:
🔜 Что такое многопоточка и зачем она нужна.
🔜 Как создать и настроить поток
🔜 Как остановить поток, как избежать дедлоков
🔜 Посмотрели все это на примерах

Ссылки из видео:
Первая
Вторая
Третья

Смотрите, комментируйте, задавайте вопросы! Обязательно подписывайтесь на ютуб и рутюб каналы!!!

Спасибо всем кто пришел, респект 🫡
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Типы changesets и стратегии развертывания в Liquibase

1. Основные изменения (changesets)

1.1. Создание таблиц (createTable)
Позволяет создавать новые таблицы с указанием столбцов и ограничений.

Пример (YAML):

databaseChangeLog:  
- changeSet:
id: 1
author: dev
changes:
- createTable:
tableName: users
columns:
- column:
name: id
type: BIGINT
autoIncrement: true
constraints:
primaryKey: true
nullable: false
- column:
name: username
type: VARCHAR(50)
constraints:
unique: true


Разбор:
tableName – имя таблицы.
columns – список столбцов.
constraints – ограничения (primaryKey, nullable, unique).


1.2. Добавление столбцов (addColumn)

Добавляет новый столбец в существующую таблицу.

Пример (YAML):
- changeSet:  
id: 2
author: dev
changes:
- addColumn:
tableName: users
columns:
- column:
name: email
type: VARCHAR(100)
constraints:
nullable: false


Параметры:
tableName – имя таблицы.
defaultValue – значение по умолчанию (опционально).


1.3. Изменение структуры (alterTable, modifyDataType)
Используется для изменения типа данных столбца или переименования таблицы.

Пример (YAML):
- changeSet:  
id: 3
author: dev
changes:
- alterTable:
tableName: users
columns:
- column:
name: username
type: VARCHAR(100) # Увеличение длины
- renameColumn:
tableName: users
oldColumnName: email
newColumnName: email_address


2. Управление зависимостями

2.1. Атрибуты runAlways и runOnChange
runAlways="true" – changeSet выполняется каждый раз, даже если уже был применен.
- changeSet:  
id: 4
author: dev
runAlways: true
changes:
- sql:
sql: "INSERT INTO logs (message) VALUES ('Migration executed')"
runOnChange="true" – выполняется только если содержимое changeSet’а изменилось.


2.2. Условия (preConditions)
Проверяют условия перед выполнением changeSet’а.

Пример (YAML):
- changeSet:  
id: 5
author: dev
preConditions:
- tableExists:
tableName: users
changes:
- addColumn:
tableName: users
columns:
- column:
name: status
type: VARCHAR(20)


Доступные проверки:
tableExists / tableNotExists
columnExists
sqlCheck (произвольный SQL-запрос).


3. Стратегии развертывания

3.1. Последовательное применение
ChangeSet’ы выполняются строго по порядку, указанному в databaseChangeLog.

Пример:
databaseChangeLog:  
- include:
file: db/changelog/v1.0/001-create-tables.yaml
- include:
file: db/changelog/v1.0/002-add-constraints.yaml


3.2. Параллельное выполнение
Liquibase не поддерживает параллельное выполнение changeSet’ов по умолчанию.

Однако можно:
Разделять changelog на независимые модули.
Использовать contexts для условного выполнения.


Пример:
- changeSet:  
id: 6
author: dev
context: "!prod" # Не выполнять в production
changes:
- insert:
tableName: test_data
columns:
- column:
name: value
value: "Test"


4. Поддержка разных форматов

Liquibase позволяет использовать:
YAML – лаконичный и удобный для разработчиков.
XML – строгий и структурированный.
JSON – альтернатива YAML.
SQL – для прямого написания SQL-запросов.


Пример SQL-формата:

--liquibase formatted sql  

--changeset dev:7
CREATE INDEX idx_user_email ON users(email);

--changeset dev:8 context:prod
ALTER TABLE users ADD COLUMN last_login TIMESTAMP;


#Java #middle #Liquibase
Что выведет код?

public class Task020625 {
public static void main(String[] args) {
String s1 = new String("Java");
String s2 = "Java";
String s3 = s1.intern();

System.out.println((s1 == s2) + " " + (s2 == s3));
}
}


#Tasks
Варианты ответа:
Anonymous Quiz
19%
"true true"
30%
"true false"
37%
"false true"
15%
"false false"
В чем разница между Thread и Runnable? 🤓

Ответ:

Thread — это класс, представляющий поток.

Runnable — интерфейс с методом run(), описывающий задачу для потока.

Runnable предпочтительнее, так как позволяет наследовать другой класс и использовать пулы потоков.


#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Глубокое изучение типа данных boolean в Java

Тип boolean — самый компактный и в то же время наименее числовой из всех примитивных типов в Java. Он представляет логические значения true или false и лежит в основе всех условных конструкций языка. Несмотря на простоту, поведение boolean в Java имеет ряд важных нюансов, связанных с его представлением в памяти, взаимодействием с другими типами, ограничениями и поведением на уровне JVM.

Что представляет собой boolean

Тип boolean может принимать только два значения: true и false. Он не является числовым типом и не участвует в арифметике. Java строго типизирована, поэтому невозможно, как в C или Python, неявно преобразовать boolean в число или наоборот. Это ограничение сделано для повышения читаемости и безопасности кода.

Например, такой код в Java недопустим:
int x = true; // Ошибка компиляции
if (1) { ... } // Тоже ошибка


Хранение в памяти

На уровне языка boolean воспринимается как логическое значение, но в памяти JVM его представление зависит от контекста:
При хранении в массиве или в виде поля класса, boolean может занимать целый байт или даже больше, в зависимости от выравнивания и архитектуры. В спецификации Java не указано точное количество битов, которое должен занимать boolean, только то, что он представляет true/false.

В локальных переменных boolean может быть оптимизирован компилятором и размещен в стеке наряду с другими переменными. Однако фактический объем занимаемой памяти определяется JVM и может отличаться от теоретически минимального.

На уровне байткода логические значения часто реализуются как int со значением 0 или 1, но это скрыто от разработчика и не влияет на язык напрямую.

Инициализация и значение по умолчанию

Локальные переменные типа boolean не инициализируются автоматически — попытка использовать их без явного присваивания вызовет ошибку компиляции.
Поля классов и массивов по умолчанию получают значение false.


Операции с boolean

Java предоставляет классический набор логических операций:
!a — логическое отрицание (NOT)
a && b — логическое И (AND, с коротким замыканием)
a || b — логическое ИЛИ (OR, с коротким замыканием)
a ^ b — исключающее ИЛИ (XOR)
Кроме того, возможны сравнения (==, !=) между значениями типа boolean, но не упорядоченные сравнения (<, >, <=, >=) — они не имеют смысла и запрещены.
В отличие от числовых типов, boolean не участвует в операциях сложения, вычитания или побитовых вычислений. Java запрещает такие действия на уровне компилятора.


Сравнение с другими примитивами

boolean — единственный логический тип в Java. Нет аналогов bit, flag, bool8, bool32 и т. д.
Он не является числом. В то время как char, byte, short, int, long, float и double можно свободно преобразовывать друг в друга, boolean изолирован от них.
Это делает boolean более строго типизированным и безопасным, но менее гибким, если требуется, например, сериализация логики в числовом формате.


#Java #для_новичков #beginner #boolean
Типизация и ограничения

Нельзя привести boolean к int или обратно. Даже явно: (int) true — ошибка.
Нельзя использовать boolean в качестве индекса массива или как аргумент методов, ожидающих число.
Нет Boolean.parseInt(), как у числовых типов — только Boolean.parseBoolean() с String.


Упаковка и объектный аналог

Для работы с boolean как объектом существует класс-обертка Boolean. Он используется при работе с коллекциями (List<Boolean>) или API, которые требуют объектов.

Как и другие обертки, Boolean поддерживает автоупаковку и автораспаковку:
Boolean obj = true;     // упаковка
boolean val = obj; // распаковка
Также есть кэширование значений: Boolean.TRUE и Boolean.FALSE — это единственные экземпляры класса Boolean, которые обычно и используются.


Подводные камни и особенности

Нет арифметики. Переход с языков вроде C, где true — это 1, а false — это 0, может вызвать ошибки. Java не допускает смешивания логики и чисел.
Отсутствие побитовых операций. Нельзя использовать & или | на boolean как побитовые операторы. Да, есть &, | и ^, но они действуют как логические, без короткого замыкания — в отличие от && и ||.
Нет поддержки масок и битов. Если требуется управлять отдельными битами, используют int или byte, а не boolean[].
Выражения с boolean всегда проверяются как логические. Даже if (a & b) — это проверка boolean, а не побитовая операция над числами.
Интерфейсы и структуры не позволяют оптимизировать boolean до одного бита. Например, boolean[] всегда тратит 1 байт (или больше) на элемент, а не один бит, как хотелось бы при экономии памяти. Для работы с компактными флагами используют BitSet или битовые маски на базе int.


#Java #для_новичков #beginner #boolean
Продолжаем выбирать темы для разбора и голосовать за рассмотрение предложенных! 🤓

Голосуем за тему к рассмотрению в эти выходные!

Выбираем новую тему!
(можете предложить что-то из того, что предлагали на прошлой и позапрошлых неделях и что проиграло в голосовании!)

Не стесняемся! ✌️
Please open Telegram to view this post
VIEW IN TELEGRAM
Что выведет код?

public class Task030625 {
public static void main(String[] args) {
boolean a = false;
boolean b = true;
boolean c = a != b == !b;
System.out.println(c);
}
}


#Tasks
Что такое ключевое слово synchronized? 🤓

Ответ:

synchronized обеспечивает потокобезопасность, позволяя только одному потоку выполнять блок кода или метод. Используется для предотвращения состояния гонки (race condition) при доступе к общим ресурсам.

#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Откаты (Rollback) и теги в Liquibase

Liquibase предоставляет мощные инструменты для отката изменений в базе данных, что критически важно при возникновении ошибок или необходимости вернуться к предыдущей версии схемы.

1. Типы откатов

1.1. Автоматический откат (на основе Liquibase)
Liquibase может автоматически генерировать команды отката для некоторых операций, если они указаны в changeSet.

Пример (YAML):
- changeSet:
id: 1
author: dev
changes:
- createTable:
tableName: users
columns:
- column:
name: id
type: INT
constraints:
primaryKey: true
- rollback:
dropTable:
tableName: users


Как это работает?
При выполнении liquibase update применяется createTable.
При откате (rollback) выполнится dropTable.

Какие операции поддерживают автоматический откат?
createTable → dropTable
addColumn → dropColumn
createIndex → dropIndex


Ограничения:
Не все операции имеют автоматический откат (например, сложные ALTER TABLE).
Для них требуется ручной rollback.


1.2. Ручной откат (пользовательские SQL-скрипты)
Если Liquibase не может сгенерировать откат автоматически, его можно задать вручную.

Пример (YAML):
- changeSet:
id: 2
author: dev
changes:
- sql:
sql: "ALTER TABLE users ADD COLUMN last_login TIMESTAMP"
- rollback:
sql:
sql: "ALTER TABLE users DROP COLUMN last_login"


Когда использовать?
Для сложных SQL-запросов.
Если Liquibase не поддерживает автоматический откат для операции.


2. Теги (Tags)

Теги позволяют помечать определённое состояние базы данных, чтобы позже можно было к нему вернуться.

2.1. Создание тега (tag)
Пометка текущего состояния БД.

Команда:
liquibase tag v1.0
или через changelog:

yaml
- changeSet:
id: 3
author: dev
changes:
- tagDatabase:
tag: v1.0


Где хранится информация о тегах?
В таблице DATABASECHANGELOG (поле TAG).

2.2. Откат к тегу (rollback <tag>)
Возврат базы данных к состоянию на момент создания тега.

Команда:
liquibase rollback v1.0


Как это работает?
Liquibase находит тег v1.0 в DATABASECHANGELOG.
Определяет, какие changeSet’ы были выполнены после этого тега.
Применяет откаты в обратном порядке.


Пример (YAML):
- changeSet:
id: 4
author: dev
changes:
- tagDatabase:
tag: v1.1


3. Практические сценарии отката

3.1. Отмена последнего changeSet’а
liquibase rollbackCount 1


Что произойдёт?
Liquibase откатит один последний применённый changeSet.


3.2. Восстановление до определённой версии

Вариант 1: По тегу
liquibase rollback v1.0


Вариант 2: По дате
liquibase rollbackToDate 2024-03-15


Вариант 3: По количеству changeSet’ов
liquibase rollbackCount 3  # Откатит 3 последних изменения


#Java #middle #Liquibase
4. Важные нюансы

Откат не всегда возможен
Если changeSet не содержит rollback, Liquibase не сможет его отменить автоматически.

(Пример: изменение данных (INSERT/UPDATE) требует ручного rollback.)

Теги vs. Версии
Теги — это произвольные метки (например, v1.0, prod-release).
Версии — это последовательные номера changeSet’ов.


Безопасность откатов
Всегда тестируйте rollback в dev-среде, прежде чем применять в production.
Используйте preConditions, чтобы избежать ошибок.


5. Пример полного сценария

1. Изначальный changelog:

databaseChangeLog:
- changeSet:
id: 1
author: dev
changes:
- createTable:
tableName: users
columns:
- column:
name: id
type: INT
constraints:
primaryKey: true
- rollback:
dropTable:
tableName: users

- changeSet:
id: 2
author: dev
changes:
- addColumn:
tableName: users
column:
name: username
type: VARCHAR(50)
- rollback:
dropColumn:
tableName: users
columnName: username

- changeSet:
id: 3
author: dev
changes:
- tagDatabase:
tag: v1.0


2. Применяем изменения:
liquibase update


3. Откатываемся до тега v1.0:
liquibase rollback v1.0


Результат:
Будет отменён changeSet id=2 (удалён столбец username).
Таблица users останется (так как changeSet id=1 был до тега).


#Java #middle #Liquibase