Глубокое изучение типа данных 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.
Например:
Чтобы код компилировался, нужно сделать явное приведение:
Это также относится к byte. int, в отличие от них, участвует в арифметике напрямую без преобразований, так как int — тип по умолчанию для целых чисел в Java.
Переполнение и поведение при выходе за диапазон
short, как и другие примитивные типы, не защищён от переполнения. Если результат выходит за диапазон [-32 768; 32 767], значение просто оборачивается — без исключений или предупреждений.
Это может быть источником трудноуловимых ошибок:
Беззнаковость
Как и byte, short — только знаковый тип. В Java нет беззнакового short. Если необходимо работать с диапазоном 0–65535, используется int и маска & 0xFFFF:
Применение и область использования
Оптимизация памяти. Если у вас есть массив, содержащий значения, которые гарантированно не выходят за диапазон short, можно заменить int на short и вдвое сократить объём памяти.
Работа с файлами и сетевыми протоколами. Некоторые форматы (например, WAV, BMP) и сетевые протоколы используют 16-битные поля. Для точного отражения структуры лучше использовать short, чтобы избежать лишних преобразований.
Ограничение диапазона. Как и в случае с byte, использование short может служить сигналом другим разработчикам: переменная не может иметь произвольное значение int.
Сравнение: byte vs short vs int
byte — минимальный по размеру, экономичен, но быстро переполняется. Подходит для работы с бинарными потоками, кодировками, цветовыми компонентами.
short — компромисс между byte и int. Используется реже, но уместен в структурированных форматах, при массовой обработке чисел с ограниченным диапазоном.
int — тип по умолчанию. Безопасный, удобный, редко переполняется. Но при массовой обработке больших объёмов данных может оказаться избыточным по памяти.
Пример: обрезка типа при записи
#Java #для_новичков #beginner #short
Тип 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
Что выведет код?
#Tasks
public class Main {
public static void main(String[] args) {
short a = 10;
short b = 20;
short c = a + b;
System.out.println(c);
}
}
#Tasks
Кастомизация и адаптеры в Gson
1. Кастомные сериализаторы и десериализаторы
Gson позволяет переопределять стандартное поведение сериализации и десериализации с помощью интерфейсов JsonSerializer<T> и JsonDeserializer<T>.
1.1. Создание кастомного сериализатора (JsonSerializer<T>)
Используется, когда нужно изменить стандартное преобразование объекта в JSON.
Пример: Сериализация объекта User с особым форматированием поля email.
1.2. Создание кастомного десериализатора (JsonDeserializer<T>)
Используется, когда нужно изменить стандартное преобразование JSON в объект.
Пример: Десериализация JSON с дополнительной валидацией email.
1.3. Регистрация адаптеров через GsonBuilder
Чтобы применить кастомные сериализаторы и десериализаторы, их нужно зарегистрировать в GsonBuilder:
1.4. Пример: Кастомный формат даты
Если стандартный формат даты (Date) не подходит, можно задать свой:
#Java #middle #Gson #JsonSerializer #JsonDeserializer
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
Пример:
2.2. Использование @Expose для выборочной сериализации
Поля без @Expose игнорируются, если включена соответствующая настройка.
2.3. Полный пример кастомной конфигурации Gson
#Java #middle #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
Что выведет код?
#Tasks
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
В чем разница между public, private, protected и default модификаторами доступа? 🤓
Ответ:Модификаторы доступа определяют видимость элементов класса:
🔜 public: доступен отовсюду.
🔜 private: доступен только внутри класса.
🔜 protected: доступен в пакете и в подклассах (даже в других пакетах).
🔜 default (без модификатора): доступен только внутри пакета.
#собеседование
Ответ:
#собеседование
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, а потом результат приводится к long. Чтобы избежать переполнения, нужно один из операндов явно сделать long:
Переполнение и wraparound
Тип long, несмотря на огромный диапазон, всё равно может переполниться. Если результат выходит за пределы диапазона, он не вызывает исключения, а оборачивается по модулю 2⁶⁴:
Беззнаковость и побитовая работа
В Java нет беззнакового long. Для имитации поведения 64-битного беззнакового числа можно использовать BigInteger, либо применять побитовые маски и операторы, чтобы интерпретировать старшие биты корректно.
Например:
С 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
Тип данных 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
Что выведет код?
#Tasks
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