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

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

Наш канал на RUTube - https://rutube.ru/channel/37896292/
Download Telegram
Глубокое изучение типа данных char в Java

Тип char в Java — это единственный примитивный тип, предназначенный для хранения символов. Однако под «символом» в контексте Java подразумевается не просто буква или цифра, а 16-битное значение, соответствующее одному коду Unicode. Это делает char более универсальным, чем аналогичные типы в других языках (например, char в C/C++ — это просто байт).

Тем не менее, с учетом особенностей кодировки Unicode, поведения в выражениях и сравнении с другими примитивами, char — не такой уж простой тип.

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

В Java char — это целое беззнаковое значение, хранящееся в 16 битах (2 байта). Диапазон значений — от 0 до 65 535. Это соответствует возможным значениям Unicode Code Units, используемым для представления символов в кодировке UTF-16.

В отличие от byte, short, int и других числовых типов, char:
Не поддерживает отрицательные значения.
Не используется в арифметике напрямую (но может быть преобразован в int).
Представляет не число, а код символа, хотя технически это просто целое значение.


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

Как и все примитивные типы, char хранится в стеке, если используется как локальная переменная, и в куче — если является полем объекта. В обоих случаях он занимает ровно 2 байта (16 бит).

Символ и кодировка Unicode

Java изначально проектировалась с поддержкой международного текста, поэтому char хранит значение по спецификации Unicode. Однако важно понимать: char хранит одну кодовую единицу UTF-16, а не обязательно один графический символ.

Некоторые символы Unicode (например, эмодзи или древние алфавиты) имеют коды за пределами 16 бит. Такие символы представлены в UTF-16 двумя char, известными как суррогатная пара.
Это значит, что один char — это не всегда "один символ", что может привести к ошибкам при разборе строк, итерации по символам или определении длины строки.

Пример:
String s = "😀";
System.out.println(s.length()); // 2, а не 1
Здесь length() возвращает 2, потому что символ представлен двумя char.


Экранирование символов

Литералы char записываются в одиночных кавычках:
char c = 'A';


Java поддерживает экранированные символы, например:
'\n' — перевод строки
'\t' — табуляция
'\'' — апостроф
'\\' — обратный слеш
'\u0041' — Unicode-последовательность (в данном случае это символ 'A')


Unicode-последовательности (\uXXXX) можно использовать даже в имени переменной или в коде, до начала компиляции — они обрабатываются на уровне лексического анализатора, еще до построения синтаксического дерева.

#Java #для_новичков #beginner #char
👍3
Поведение в выражениях и преобразования

Несмотря на то, что char — это не числовой тип, он может участвовать в арифметике. В любых выражениях с участием char он неявно преобразуется в int.
char c = 'A';
int x = c + 1; // x == 66


Но обратное требует явного приведения:
char next = (char)(c + 1); // 'B'
Аналогично, попытка присвоить результат арифметики напрямую переменной типа char вызовет ошибку компиляции без приведения.


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

В отличие от byte, short, int, char — беззнаковый.
Он занимает 2 байта, как short, но short — знаковый (-32 768 до 32 767), а char — 0 до 65 535.
В арифметике char ведет себя как int, автоматически повышая тип.
В отличие от String, char представляет одну кодовую единицу, а не последовательность символов.
В отличие от boolean, char может участвовать в арифметических выражениях и преобразованиях.


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

Локальные переменные char должны быть явно инициализированы.
Поля классов по умолчанию получают значение \u0000, что соответствует нулевому символу Unicode (не отображается в консоли).


Частые ошибки и подводные камни

Суррогатные пары. При работе со строками, содержащими символы за пределами BMP (Basic Multilingual Plane), важно использовать методы вроде codePointAt() и Character.toChars(), чтобы не потерять часть символа.
Арифметика с char. Все выражения приводятся к int, что может привести к неожиданному переполнению или необходимости явного приведения.
Сравнение символов. Операции c1 < c2 работают корректно, но сравниваются числовые значения Unicode, а не "лексикографическое положение" в каком-либо языке.
Обработка управляющих символов. Символы вроде '\0', '\n', '\r' видны в коде, но не обязательно видны в выводе — их эффект зависит от среды (консоль, IDE, файл и т.д.).


#Java #для_новичков #beginner #char
👍2
Что выведет код?

public class Task300525 {
public static void main(String[] args) {
char c = 'A';
c += 1.5;
System.out.println(c);
}
}


#Tasks
👍1
Варианты ответа:
Anonymous Quiz
4%
'A'
11%
'B'
11%
'C'
74%
Ошибка компиляции
👍2
Продолжаем выбирать темы для разбора и голосовать за рассмотрение предложенных! 🤓

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

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

Не стесняемся! ✌️
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
В чем разница между throw и throws? 🤓

Ответ:

throw используется для явного выброса исключения, например: throw new IOException();.

throws указывается в сигнатуре метода, чтобы сообщить, какие проверяемые исключения он может выбросить, например: void method() throws IOException.


#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
После проведенного голосования, определилась тема для рассмотрения в выходные - MVC.

Приступим'с


Архитектурный шаблон MVC в Java Spring: теория, правила, ошибки

MVC (Model–View–Controller) — это один из фундаментальных архитектурных паттернов в программной инженерии, направленный на разделение приложения на логически независимые компоненты. Его основная цель — изолировать пользовательский интерфейс от бизнес-логики и доступа к данным. В экосистеме Java фреймворк Spring реализует этот шаблон через модуль Spring MVC.

Теория: что такое MVC

Шаблон MVC подразумевает разделение приложения на три слоя:

Model (Модель)

Модель инкапсулирует бизнес-логику и данные приложения. Она может включать:
Сущности базы данных (например, классы с аннотацией @Entity).
Репозитории (
@Repository), обеспечивающие доступ к данным.
Сервисный слой (
@Service), реализующий бизнес-логику.
DTO (Data Transfer Objects) — объекты для обмена данными между слоями.


❗️Модель не должна зависеть от представления или контроллера.

View (Представление)

Представление отвечает за отображение информации пользователю. В Spring это обычно:
HTML-шаблоны (например, на Thymeleaf).
JSON-ответы (в случае REST API).
Альтернативные форматы (XML, PDF и пр.).
View должен быть как можно более простым и не содержать бизнес-логики.


Controller (Контроллер)

Контроллер — связующее звено между внешним миром (HTTP-запросами) и внутренними слоями приложения. Он:
Принимает входные данные.
Делегирует выполнение модели.
Выбирает и возвращает подходящее представление.
Контроллеры в Spring создаются с помощью аннотаций
@Controller или @RestController.

Жизненный цикл HTTP-запроса в Spring MVC


🔵Пользователь отправляет HTTP-запрос.
🔵DispatcherServlet перехватывает запрос.
🔵Система HandlerMapping находит соответствующий контроллер.
🔵Контроллер вызывает метод бизнес-логики через @Service.
🔵Сервис взаимодействует с репозиториями и возвращает результат.
🔵Контроллер передаёт данные во View (или сериализует их в JSON).
🔵Ответ возвращается клиенту.

Роль слоёв в приложении Spring


Контроллер
Контроллер должен быть «тонким» и не содержать бизнес-логики. Его задача — маршрутизировать запросы и собирать данные, необходимые представлению.

Пример (корректный):
@GetMapping("/users")
public List<UserDto> getUsers(Model model) {
return userService.getAllUsers();
}


Неправильный пример (контроллер содержит логику):
@GetMapping("/users")
public List<UserDto> getUsers(Model model) {
List<User> users = userRepository.findAll();
return users.stream()
.map(user -> new UserDto(user.getId(), user.getName()))
.collect(Collectors.toList());
}


Сервисный слой

Сервисный слой содержит бизнес-логику, правила обработки данных, валидацию, логи, обработку ошибок. Он изолирован от HTTP и представления. Сервисы не должны напрямую зависеть от Model, HttpServletRequest или аннотаций Spring MVC.

Пример:
@Service
public class UserService {
@Autowired
private UserRepository userRepository;

public List<UserDto> getAllUsers() {
return userRepository.findAll().stream()
.map(user -> new UserDto(user.getId(), user.getName()))
.collect(Collectors.toList());
}
}


Репозиторий

Репозиторий отвечает за доступ к данным. Он инкапсулирует работу с базой и предоставляет CRUD-интерфейс.
public interface UserRepository extends JpaRepository<User, Long> {}


#Java #для_новичков #beginner #on_request #mvc
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Распространённые ошибки

1. Логика в контроллерах
Признак: контроллер становится "сервисом", содержащим условия, циклы, доступ к БД. Это нарушает принципы чистой архитектуры и усложняет тестирование.

2. Использование Entity в представлении
Передача @Entity напрямую в шаблон может привести к:
Утечке данных (например, паролей).
Ошибкам LazyInitializationException.
Сильной связанности представления с базой данных.
Решение: использовать DTO или ViewModel.


3. Жёсткая связность между слоями
View не должно зависеть от Repository, а Controller — от Entity. Каждый слой должен взаимодействовать только с соседним.

4. Отсутствие DTO
Использование одной и той же модели во всех сценариях ведёт к путанице и проблемам безопасности. Лучше использовать отдельные классы:
UserCreateRequest
UserResponse
UserUpdateRequest


Рекомендации по проектированию

Структура проекта

Хорошей практикой является разделение кода по слоям:
com.example.myapp
├── controller
├── service
│ └── impl
├── repository
├── dto
├── model
├── config


URL-дизайн

Соблюдайте RESTful-стиль:
GET /users — получить список пользователей.
GET /users/{id} — получить конкретного пользователя.
POST /users — создать.
PUT /users/{id} — обновить.
DELETE /users/{id} — удалить.


Использование DTO
public class UserResponse {
private Long id;
private String name;
}


public class UserCreateRequest {
private String name;
private String email;
}


Расширения и адаптации MVC

SPA + API
При использовании Vue, React или Angular, представление полностью переносится на фронтенд. В этом случае Spring работает как REST API с @RestController, и классическая схема MVC трансформируется в «REST + JSON».

Поддержка реактивности
Spring WebFlux реализует неблокирующую модель с Mono и Flux, сохраняя при этом логическую структуру MVC. Подходит для высоконагруженных и асинхронных приложений.

Тестирование компонентов MVC


Контроллеры — @WebMvcTest, MockMvc.
Сервисы —
@SpringBootTest или с моками (@MockBean).
Репозитории —
@DataJpaTest.

#Java #для_новичков #beginner #on_request #mvc
👍5
This media is not supported in your browser
VIEW IN TELEGRAM
Мой сервис стучится в соседнее API 🧑‍💻😂

https://t.me/Java_for_beginner_dev

#Mems
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥2
Есть предложение встретиться завтра в 16:00 по МСК на лайвкодинг!

Тема будет: Многопоточка на примерах
Anonymous Poll
33%
О, интересно, я приду ✈️
27%
Блииин, я хочу, но нет возможности 🤷‍♀️
39%
Посмотрю в записи 👌
0%
Не приду. Фигню какую то рассматриваете 🤢
👍2
Всем привет! ✌️

Приглашаю всех желающих сегодня собраться в Яндекс.Телемост в 16:00 по МСК!

В этот раз, @rKiraLis39 расскажет и покажет много интересного по многопоточке.

И даже если раньше вы все это знали, лишним повторить не будет.

Приходите, это хороший шанс позадавать вопросы 🧑‍💻

Как всегда жду всех! 🫡
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
«Ты не программируешь — ты притворяешься, что учишься»

Однажды я купил себе книгу Spring 5.
Большая, толстая, со множеством, страниц. Неся её домой я живо представлял себе, что уже завтра буду писать Spring-приложения, направо и налево.
🥳

И я честно прочитал ее. А потом еще разок. 🤓

И ПОНЯЛ, ЧТО НИЧЕГО НЕ ПОНЯЛ!

Точнее понять то понял (книга ж на русском
🤪), да вот открыв IDEA яснее мне ничего не стало.

Как это начать писать то? 😔

И вот тут, друзья, скрывается одна из потаённых реальностей обучения:

99% "учеников" не учатся. Они просто создают иллюзию прогресса: читают, смотрят, копят курсы — но не пишут код.


🚨 Пойми:

🔵Купить и прочитать хорошие книги ≠ уметь программировать.
Пока ты не сел и не написал — ты не учишься.


🔵 Смотреть популярные видео с каналов по программированию ≠ учить Java.
Тебе приятно, когда ты "в теме" — но это ложное ощущение движения.


🔵 Количество открытых вкладок в браузере с умными статьями ≠ умный ты.
Чтение статей создаёт видимость прогресса, но мозг это не фиксирует как навык.


🔵 Пока ты изображаешь, другие сдают тестовые и получают офферы.
Для тебя это должна быть не мотивация, а ультиматум: начни делать или отойди в сторону.


🔵 Месяц «обучения без практики» = 0% роста = потерянное время.
Притворяться — удобно. Но дорого


✔️ Поэтому прямо сейчас:

➡️ Закрой вкладку с курсами. Открой IDE. 🧑‍💻
➡️ Придумай и напиши что-то ужасное. (И пусть оно не работает. Но ты хотя бы начал). 😈
➡️ И да, будет больно. Будет стыдно (если никому не показывать, то не очень - только перед собой)😭
➡️Но это единственный путь, на котором ты реально сдвинешься с мёртвой точки. 💪


А я, все таки победил Spring.
Правда потом, книгу почти не открывал, только для уточнения совсем уж непонятных деталей.

Просто, после написания очередного таск-менеджера, незнакомых аннотаций как будто не осталось, пришло понимание, как работает тот или иной метод, исчез страх "что-то сделать не так".


Поэтому

Просто
Начни
ПИСАТЬ КОД


😎

#motivation
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥11👍11
Предлагаем темы для разбора и публикации! 📖

В комментариях к данному посту предлагайте вопросы, которые вы хотели бы увидеть максимально подробно разобранными в постах, а если будет интересно то и на видео.

Голосование будет проводиться всю неделю, а статья или видео - выходить по выходным.

Примерные правила:
🟢 темы, не выше уровня middle, чтоб был интерес общим.
🟢 один человек - одна тема.
🟢Тема должна быть отдельным теоретически-практическим вопросом. Готовый проект - это не тема!

Жду Ваших предложений! 👏
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Выбираем темы предложенные на этой неделе!
Anonymous Poll
31%
JavaMailSender
14%
AOP
20%
IO/NIO
20%
Maven
14%
JSON
👍3
Встреча создана!

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
👍8
📌 Факт дня:

А вы знали, что первая компьютерная система "автодополнения текста" появилась в 1970-х?

Система текстового редактора EMACS, созданная в 1976 году Ричардом Столлманом, впервые предложила автодополнение для команд и текста. Это стало прообразом современных функций автодополнения в поисковиках и редакторах кода. EMACS был разработан как набор макросов для редактора TECO (от "Editing MACroS"). Это был один из первых редакторов, который позволял пользователям расширять и настраивать свою функциональность с помощью языка Emacs Lisp.


Proof

#facts
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Типы 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
👍2
Что выведет код?

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
👍1