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

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

Наш канал на RUTube - https://rutube.ru/channel/37896292/
Download Telegram
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Глубокое изучение типа данных short в Java: сравнение с byte и int

Тип short в Java — это примитивный тип, представляющий собой 16-битное целое число со знаком. Он занимает 2 байта памяти и служит компромиссным решением между компактным byte и универсальным int. Несмотря на то, что short используется относительно редко, его понимание важно при оптимизации памяти и взаимодействии с внешними системами.

Диапазон и внутреннее представление


Тип short может хранить значения от -32 768 до 32 767. Как и все знаковые целочисленные типы в Java, short использует формат дополнительного кода (two’s complement). Самый старший (16-й) бит используется для знака: 0 — положительное число, 1 — отрицательное.

Это значит, что в 16 бит можно закодировать 2¹⁶ различных значений: половина для положительных чисел (включая 0), половина для отрицательных.

Для сравнения:
byte — 8 бит, диапазон: -128 до 127
short — 16 бит, диапазон: -32 768 до 32 767
int — 32 бита, диапазон: примерно -2.1 млрд до 2.1 млрд

Такой диапазон делает short пригодным для хранения небольших чисел, например, размеров, координат, портов, идентификаторов, когда byte мал, а int избыточен.

Память и размещение

short занимает 2 байта, в отличие от byte (1 байт) и int (4 байта). Это может быть важно при работе с большими массивами. Например, массив из миллиона short займёт 2 МБ, а массив int — уже 4 МБ.

Как и другие примитивные типы, short:
хранится в стеке, если это локальная переменная;
размещается в куче, если это поле объекта;
автоматически удаляется при выходе переменной из области видимости или при сборке мусора (если внутри объекта).


Арифметика и повышение типов

Важный момент: при любом арифметическом выражении, даже если оба операнда имеют тип short, результат всегда приводится к int. Это правило относится ко всем типам, младше int.

Например:
short a = 1000;
short b = 2000;
short c = a + b; // Ошибка компиляции


Чтобы код компилировался, нужно сделать явное приведение:
short c = (short)(a + b);


Это также относится к byte. int, в отличие от них, участвует в арифметике напрямую без преобразований, так как int — тип по умолчанию для целых чисел в Java.

Переполнение и поведение при выходе за диапазон

short, как и другие примитивные типы, не защищён от переполнения. Если результат выходит за диапазон [-32 768; 32 767], значение просто оборачивается — без исключений или предупреждений.

Это может быть источником трудноуловимых ошибок:
short s = 32_767;
s++; // теперь s = -32_768


Беззнаковость

Как и byte, short — только знаковый тип. В Java нет беззнакового short. Если необходимо работать с диапазоном 0–65535, используется int и маска & 0xFFFF:
short s = -1;
int unsigned = s & 0xFFFF; // результат: 65535


Применение и область использования


Оптимизация памяти. Если у вас есть массив, содержащий значения, которые гарантированно не выходят за диапазон short, можно заменить int на short и вдвое сократить объём памяти.
Работа с файлами и сетевыми протоколами. Некоторые форматы (например, WAV, BMP) и сетевые протоколы используют 16-битные поля. Для точного отражения структуры лучше использовать short, чтобы избежать лишних преобразований.
Ограничение диапазона. Как и в случае с byte, использование short может служить сигналом другим разработчикам: переменная не может иметь произвольное значение int.

Сравнение: byte vs short vs int

byte — минимальный по размеру, экономичен, но быстро переполняется. Подходит для работы с бинарными потоками, кодировками, цветовыми компонентами.
short — компромисс между byte и int. Используется реже, но уместен в структурированных форматах, при массовой обработке чисел с ограниченным диапазоном.
int — тип по умолчанию. Безопасный, удобный, редко переполняется. Но при массовой обработке больших объёмов данных может оказаться избыточным по памяти.

Пример: обрезка типа при записи
short s = (short) 40000;
System.out.println(s); // Выведет -25536
Потому что 40000 не помещается в short, и лишние биты отбрасываются.


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

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

Выбираем новую тему!

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

public class Main {
public static void main(String[] args) {
short a = 10;
short b = 20;
short c = a + b;
System.out.println(c);
}
}


#Tasks
Варианты ответа:
Anonymous Quiz
62%
30
2%
0
36%
Ошибка компиляции
0%
-10
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Кастомизация и адаптеры в Gson

1. Кастомные сериализаторы и десериализаторы

Gson позволяет переопределять стандартное поведение сериализации и десериализации с помощью интерфейсов JsonSerializer<T> и JsonDeserializer<T>.

1.1. Создание кастомного сериализатора (JsonSerializer<T>)
Используется, когда нужно изменить стандартное преобразование объекта в JSON.

Пример: Сериализация объекта User с особым форматированием поля email.
public class User {
private String name;
private String email;

// Конструкторы, геттеры и сеттеры
}

public class UserSerializer implements JsonSerializer<User> {
@Override
public JsonElement serialize(User user, Type typeOfSrc, JsonSerializationContext context) {
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("name", user.getName());
jsonObject.addProperty("email", user.getEmail().toLowerCase()); // Приводим email к нижнему регистру
return jsonObject;
}
}


1.2. Создание кастомного десериализатора (JsonDeserializer<T>)
Используется, когда нужно изменить стандартное преобразование JSON в объект.

Пример: Десериализация JSON с дополнительной валидацией email.


public class UserDeserializer implements JsonDeserializer<User> {
@Override
public User deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
JsonObject jsonObject = json.getAsJsonObject();
String name = jsonObject.get("name").getAsString();
String email = jsonObject.get("email").getAsString();

if (!email.contains("@")) {
throw new JsonParseException("Invalid email format");
}

return new User(name, email);
}
}


1.3. Регистрация адаптеров через GsonBuilder
Чтобы применить кастомные сериализаторы и десериализаторы, их нужно зарегистрировать в GsonBuilder:

Gson gson = new GsonBuilder()
.registerTypeAdapter(User.class, new UserSerializer()) // Сериализатор
.registerTypeAdapter(User.class, new UserDeserializer()) // Десериализатор
.create();

// Сериализация
User user = new User("John", "John@Example.com");
String json = gson.toJson(user); // {"name":"John","email":"john@example.com"}

// Десериализация
User parsedUser = gson.fromJson(json, User.class);


1.4. Пример: Кастомный формат даты
Если стандартный формат даты (Date) не подходит, можно задать свой:

public class DateSerializer implements JsonSerializer<Date> {
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("dd.MM.yyyy");

@Override
public JsonElement serialize(Date date, Type typeOfSrc, JsonSerializationContext context) {
return new JsonPrimitive(dateFormat.format(date));
}
}

Gson gson = new GsonBuilder()
.registerTypeAdapter(Date.class, new DateSerializer())
.create();

Date now = new Date();
String json = gson.toJson(now); // "12.05.2025"


#Java #middle #Gson #JsonSerializer #JsonDeserializer
2. Настройка Gson через GsonBuilder

GsonBuilder позволяет гибко настраивать поведение Gson.

2.1. Основные методы настройки
.setPrettyPrinting(): Форматирует JSON с отступами для читаемости
.serializeNulls(): Сериализует поля со значением null (по умолчанию они пропускаются)
.excludeFieldsWithoutExposeAnnotation(): Игнорирует поля без аннотации
@Expose

Пример:
Gson gson = new GsonBuilder()
.setPrettyPrinting() // Красивый вывод JSON
.serializeNulls() // Включает null-поля
.excludeFieldsWithoutExposeAnnotation() // Только помеченные @Expose
.create();


2.2. Использование @Expose для выборочной сериализации
Поля без @Expose игнорируются, если включена соответствующая настройка.

public class User {
@Expose
private String name; // Будет сериализовано

private String password; // Не будет сериализовано
}

Gson gson = new GsonBuilder()
.excludeFieldsWithoutExposeAnnotation()
.create();

User user = new User("John", "secret");
String json = gson.toJson(user); // {"name":"John"}


2.3. Полный пример кастомной конфигурации Gson

Gson gson = new GsonBuilder()
.setPrettyPrinting()
.serializeNulls()
.setDateFormat("dd.MM.yyyy") // Формат даты по умолчанию
.registerTypeAdapter(User.class, new UserSerializer())
.excludeFieldsWithoutExposeAnnotation()
.create();


#Java #middle #Gson #GsonBuilder
Продолжаем выбирать темы для разбора и голосовать за рассмотрение предложенных! 🤓

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

Выбираем новую тему!

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

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

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


#Tasks
Варианты ответа:
Anonymous Quiz
19%
false, false
24%
true, true
24%
false, true
32%
true, false
В чем разница между public, private, protected и default модификаторами доступа? 🤓

Ответ: Модификаторы доступа определяют видимость элементов класса:
🔜 public: доступен отовсюду.
🔜 private: доступен только внутри класса.
🔜 protected: доступен в пакете и в подклассах (даже в других пакетах).
🔜 default (без модификатора): доступен только внутри пакета.

#собеседование
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
Глубокое изучение типа данных long в Java: сравнение с byte, short и int

Тип данных long в Java — это 64-битное целое число со знаком. Он используется, когда диапазона int недостаточно для представления чисел, особенно в финансовых расчётах, временных метках, системах счёта, генерации идентификаторов и других задачах, связанных с большими значениями.

Размер и диапазон

long занимает 8 байт (64 бита) и позволяет представлять значения от -9 223 372 036 854 775 808 до 9 223 372 036 854 775 807. Это примерно ±9 квинтиллионов.

Для сравнения:
byte: 1 байт, от -128 до 127
short: 2 байта, от -32 768 до 32 767
int: 4 байта, от -2.1 млрд до 2.1 млрд


Когда ни byte, ни short, ни даже int не покрывают диапазон значений — long становится необходимостью.

Внутреннее представление

Как и остальные знаковые целые типы в Java, long реализован через дополнительный код (two’s complement). Старший (64-й) бит отвечает за знак: 0 — положительное число или ноль, 1 — отрицательное. Всё остальное аналогично другим типам, но с удвоенным количеством бит по сравнению с int.

Работа с памятью

long — примитивный тип, поэтому:
локальные переменные long хранятся в стеке;
поля объектов — в куче;
память управляется виртуальной машиной Java автоматически: выделяется при создании переменной, освобождается при выходе из области видимости (для локальных) или сборке мусора (для объектов).
Массив long[] из миллиона элементов потребует 8 МБ памяти, тогда как int[] — всего 4 МБ, а byte[] — 1 МБ. Это важно учитывать при проектировании систем, чувствительных к объёму памяти.


Арифметика и автоматическое повышение типов

Арифметика с long происходит без повышения до int, в отличие от byte и short, которые автоматически продвигаются до int в выражениях. Однако, при использовании int и long в одном выражении, результат будет long.

Пример:
int a = 1_000_000_000;
int b = 3;
long result = a * b; // результат может быть неверным!


Здесь сначала перемножаются два int, а потом результат приводится к long. Чтобы избежать переполнения, нужно один из операндов явно сделать long:
long result = (long) a * b; // безопасно


Переполнение и wraparound

Тип long, несмотря на огромный диапазон, всё равно может переполниться. Если результат выходит за пределы диапазона, он не вызывает исключения, а оборачивается по модулю 2⁶⁴:
long x = Long.MAX_VALUE;
x++;
System.out.println(x); // выведет отрицательное число: Long.MIN_VALUE
Это поведение аналогично тому, что происходит с int, short и byte, но требует повышенного внимания при работе с предельными значениями.


Беззнаковость и побитовая работа

В Java нет беззнакового long. Для имитации поведения 64-битного беззнакового числа можно использовать BigInteger, либо применять побитовые маски и операторы, чтобы интерпретировать старшие биты корректно.

Например:
long l = -1L;
String binary = Long.toBinaryString(l); // все 64 бита — единицы


С Java 8 появилась поддержка методов для unsigned арифметики: Long.divideUnsigned, Long.toUnsignedString и т.п., но сами типы остались только знаковыми.

Сравнение с младшими типами

byte и short — экономны по памяти, но быстро переполняются. Используются в низкоуровневом коде, где важен каждый байт.
int — универсален, безопасен по диапазону для большинства задач.
long — выбор для работы с большими числами, когда int недостаточен.
Однако, использование long без необходимости может привести к перерасходу памяти — особенно в коллекциях, структурах данных, больших массивах. Используйте long там, где это действительно оправдано.


Особенности и рекомендации

При передаче литералов типа long, добавляйте суффикс L, чтобы избежать ошибочного приведения к int:
long big = 3000000000L; // без 'L' это вызовет переполнение int
Проверяйте выражения на потенциальное переполнение при арифметике. Для критических расчётов используйте Math.addExact(), Math.multiplyExact() — они выбрасывают ArithmeticException при переполнении.
Если требуется более 64 бит — используйте BigInteger. Это объектный тип, не примитив, но позволяет работать с произвольно большими целыми числами.



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

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

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

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

public class Task220525 {
public static void main(String[] args) {
long a = 1_000_000_000 * 3_000;
long b = 1_000_000_000L * 3_000;
System.out.println(a == b);
}
}


#Tasks
Зачем нужен метод main в Java? 🤓

Ответ: Метод public static void main(String[] args) — точка входа в программу. JVM вызывает его при запуске приложения. Он должен быть public и static, чтобы JVM могла его вызвать без создания экземпляра класса.

В новых версиях Java (21 и выше) метод main не обязателен в строгом виде для простых программ благодаря неименованным классам и упрощённым методам main. Однако для большинства реальных приложений и для совместимости с более ранними версиями Java традиционный метод public static void main(String[] args) всё ещё необходим.

#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM