Работа с коллекциями, вложенными объектами и generic-типами в Gson
1. Работа с коллекциями
Сериализация/десериализация списков (List<T>)
Пример с List<String>:
Проблема: При использовании List.class тип элементов стирается. Для generic-типов нужен TypeToken.
Использование TypeToken для generic-типов
Пример с массивами
Работа с Map<String, Object>
2. Вложенные объекты и сложные структуры
Объекты внутри объектов
Пример JSON с вложенностью:
Соответствующие Java-классы:
Десериализация вложенного объекта
Сериализация сложного объекта
Как обрабатываются вложенности
Gson рекурсивно обходит все поля объекта.
Для каждого вложенного объекта создается новый экземпляр.
Поддерживается любая глубина вложенности.
Пример с коллекцией вложенных объектов
JSON:
Java-классы:
Десериализация:
#Java #middle #Gson
1. Работа с коллекциями
Сериализация/десериализация списков (List<T>)
Пример с List<String>:
Gson gson = new Gson();
// Сериализация списка в JSON
List<String> languages = Arrays.asList("Java", "Kotlin", "Python");
String json = gson.toJson(languages);
System.out.println(json); // ["Java","Kotlin","Python"]
// Десериализация JSON обратно в List
List<String> parsedList = gson.fromJson(json, List.class);
System.out.println(parsedList.get(0)); // Java
Проблема: При использовании List.class тип элементов стирается. Для generic-типов нужен TypeToken.
Использование TypeToken для generic-типов
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
// Создаем Type для List<String>
Type listType = new TypeToken<List<String>>() {}.getType();
// Десериализация с сохранением типа
String json = "[\"Apple\", \"Banana\"]";
List<String> fruits = gson.fromJson(json, listType);
System.out.println(fruits.get(0).toUpperCase()); // APPLE (без TypeToken был бы Object!)
Пример с массивами
// Сериализация массива
int[] numbers = {1, 2, 3};
String numbersJson = gson.toJson(numbers);
System.out.println(numbersJson); // [1,2,3]
// Десериализация обратно в массив
int[] parsedNumbers = gson.fromJson(numbersJson, int[].class);
System.out.println(parsedNumbers[0]); // 1
Работа с Map<String, Object>
// Сериализация Map
Map<String, Object> data = new HashMap<>();
data.put("name", "John");
data.put("age", 30);
data.put("skills", Arrays.asList("Java", "SQL"));
String mapJson = gson.toJson(data);
System.out.println(mapJson);
// {"skills":["Java","SQL"],"name":"John","age":30}
// Десериализация Map
Type mapType = new TypeToken<Map<String, Object>>() {}.getType();
Map<String, Object> parsedMap = gson.fromJson(mapJson, mapType);
System.out.println(parsedMap.get("name")); // John
2. Вложенные объекты и сложные структуры
Объекты внутри объектов
Пример JSON с вложенностью:
{
"name": "Alice",
"address": {
"city": "New York",
"street": "5th Avenue"
}
}
Соответствующие Java-классы:
class Address {
private String city;
private String street;
// Конструктор, геттеры и сеттеры
public Address(String city, String street) {
this.city = city;
this.street = street;
}
public String getCity() { return city; }
public String getStreet() { return street; }
}
class Person {
private String name;
private Address address;
// Конструктор, геттеры и сеттеры
}
Десериализация вложенного объекта
String personJson = """
{
"name": "Alice",
"address": {
"city": "New York",
"street": "5th Avenue"
}
}
""";
Gson gson = new Gson();
Person person = gson.fromJson(personJson, Person.class);
System.out.println(person.getName()); // Alice
System.out.println(person.getAddress().getCity()); // New York
Сериализация сложного объекта
Address address = new Address("Berlin", "Main Street");
Person person = new Person("Bob", address);
String json = gson.toJson(person);
System.out.println(json);
// {"name":"Bob","address":{"city":"Berlin","street":"Main Street"}}
Как обрабатываются вложенности
Gson рекурсивно обходит все поля объекта.
Для каждого вложенного объекта создается новый экземпляр.
Поддерживается любая глубина вложенности.
Пример с коллекцией вложенных объектов
JSON:
{
"team": "Developers",
"members": [
{
"name": "John",
"role": "Backend"
},
{
"name": "Anna",
"role": "Frontend"
}
]
}
Java-классы:
class TeamMember {
private String name;
private String role;
// конструктор и геттеры
}
class Team {
private String teamName;
private List<TeamMember> members;
// конструктор и геттеры
}
Десериализация:
Type teamType = new TypeToken<Team>() {}.getType();
Team team = gson.fromJson(jsonString, teamType);
#Java #middle #Gson
👍3
Продолжаем выбирать темы для разбора и голосовать за рассмотрение предложенных! 🤓
Голосуем за тему к рассмотрению в эти выходные!
Выбираем новую тему!
Не стесняемся!✌️
Голосуем за тему к рассмотрению в эти выходные!
Выбираем новую тему!
Не стесняемся!
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Что выведет код?
#Tasks
public class Task190525 {
public static void main(String[] args) {
String s1 = "Java";
String s2 = s1.concat('\u00A9');
System.out.println(s2);
}
}
#Tasks
👍1
👍1
"Стартапы — это марафон, а не спринт."
Джастин Кан, основатель Twitch, сказал это в 2014 году в интервью Y Combinator, подчеркивая терпение в разработке успешного стартапа.
Биография
хааабр
#Citation #Biography
Please open Telegram to view this post
VIEW IN TELEGRAM
Wikipedia
Justin Kan
Justin Kan (born July 16, 1983) is an American internet entrepreneur and investor. He is the co-founder of live video platforms Justin.tv and Twitch, as well as the mobile social video application Socialcam. He was also the co-founder and former CEO of law…
👍1
Глубокое изучение типа данных 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
👍3
Продолжаем выбирать темы для разбора и голосовать за рассмотрение предложенных! 🤓
Голосуем за тему к рассмотрению в эти выходные!
Выбираем новую тему!
Не стесняемся!✌️
Голосуем за тему к рассмотрению в эти выходные!
Выбираем новую тему!
Не стесняемся!
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Что выведет код?
#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
👍1
👍4
А вы знали, что первый "цифровой кошелёк" появился в 1990 году?
Корни цифровых кошельков уходят корнями в 1990-е годы, когда Дэвид Чаум представил DigiCash, одну из первых цифровых валют, для транзакций которых требовался цифровой кошелек (DigiCash, 1990). Новаторская работа Чаума в области криптографических методов заложила основу для безопасных онлайн-транзакций.
proof
#facts
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
"Хороший продукт решает одну проблему лучше всех."
Тони Фаделл, создатель iPod, сказал это в 2015 году на конференции TED, описывая философию дизайна.
Биография
#Citation #Biography
Please open Telegram to view this post
VIEW IN TELEGRAM
Wikipedia
Фаделл, Тони
Тони Фаделл (англ. Anthony M. Fadell; род. , ) — американский топ-менеджер. Бывший старший директор департамента по разработке и выпуску плеера iPod от Apple.
👍1
Кастомизация и адаптеры в 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
👍4
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
👍5
Продолжаем выбирать темы для разбора и голосовать за рассмотрение предложенных! 🤓
Голосуем за тему к рассмотрению в эти выходные!
Выбираем новую тему!
Не стесняемся!✌️
Голосуем за тему к рассмотрению в эти выходные!
Выбираем новую тему!
Не стесняемся!
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Что выведет код?
#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
👍1
👍2
В чем разница между public, private, protected и default модификаторами доступа? 🤓
Ответ:Модификаторы доступа определяют видимость элементов класса:
🔜 public: доступен отовсюду.
🔜 private: доступен только внутри класса.
🔜 protected: доступен в пакете и в подклассах (даже в других пакетах).
🔜 default (без модификатора): доступен только внутри пакета.
#собеседование
Ответ:
#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
А вы знали, что первый компьютерный "патч" был физическим?
Во времена, когда для загрузки программ в компьютеры использовались перфокарты или бумажные ленты, разработчики программ распространяли патчи в виде перфокарт с отличным от первоначального набором перфорации или указывали на перфоленте места, которые следует изменить. Пользователи заменяли соответствующие перфокарты в стопке или вырезали помеченную часть ленты и вклеивали вместо неё новый кусок программы. Тогда же и возникло название «patch» (англ. patch, буквально — «заплатка»).
proof
#facts
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
"Копировать и вставлять — это основа продуктивности."
Ларри Теслер, изобретатель функций "копировать/вставить", сказал это в 1980-х годах в Xerox PARC.
Биография
#Citation #Biography
Please open Telegram to view this post
VIEW IN TELEGRAM
Wikipedia
Теслер, Ларри
Ло́ренс Го́рдон Те́слер (англ. Lawrence Gordon Tesler; 24 апреля 1945 — 16 февраля 2020) — американский информатик, работавший в области взаимодействия человека и компьютера. Он фактически ввёл в оборот комбинацию клавиш Ctrl+C, Ctrl+V. Теслер работал в компаниях…
👍1
Глубокое изучение типа данных 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
👍4🤯2