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
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
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Работа с JsonElement и полезные советы в Gson

JsonElement, JsonObject, JsonArray — работа с JSON вручную

Библиотека Gson предоставляет классы JsonElement, JsonObject и JsonArray для ручного разбора и модификации JSON.

Основные классы:
JsonElement — базовый абстрактный класс, представляющий любой элемент JSON (объект, массив, примитив).
JsonObject — подкласс JsonElement, представляющий JSON-объект ({ ... }).
JsonArray — подкласс JsonElement, представляющий JSON-массив ([ ... ]).


Пример разбора JSON вручную:
import com.google.gson.*;
import com.google.gson.JsonObject;
import com.google.gson.JsonArray;

public class ManualJsonParsing {
public static void main(String[] args) {
String json = """
{
"name": "John",
"age": 30,
"skills": ["Java", "Kotlin"],
"address": {
"city": "New York",
"zip": "10001"
}
}
""";

JsonElement rootElement = JsonParser.parseString(json);

// Проверяем, что корневой элемент — JsonObject
if (rootElement.isJsonObject()) {
JsonObject rootObject = rootElement.getAsJsonObject();

// Доступ к примитивным полям
String name = rootObject.get("name").getAsString();
int age = rootObject.get("age").getAsInt();

System.out.println("Name: " + name);
System.out.println("Age: " + age);

// Доступ к массиву
JsonArray skills = rootObject.get("skills").getAsJsonArray();
System.out.println("Skills:");
for (JsonElement skill : skills) {
System.out.println("- " + skill.getAsString());
}

// Доступ к вложенному объекту
JsonObject address = rootObject.get("address").getAsJsonObject();
String city = address.get("city").getAsString();
String zip = address.get("zip").getAsString();

System.out.println("City: " + city);
System.out.println("Zip: " + zip);
}
}
}


Когда не знаешь точную структуру JSON

Если структура JSON может меняться, можно проверять наличие полей и их типы:
JsonObject userObject = rootElement.getAsJsonObject();

// Проверка наличия поля
if (userObject.has("email")) {
String email = userObject.get("email").getAsString();
System.out.println("Email: " + email);
} else {
System.out.println("Email not provided");
}

// Проверка типа поля
JsonElement ageElement = userObject.get("age");
if (ageElement != null && !ageElement.isJsonNull()) {
if (ageElement.isJsonPrimitive() && ageElement.getAsJsonPrimitive().isNumber()) {
int age = ageElement.getAsInt();
System.out.println("Age: " + age);
} else {
System.out.println("Age is not a number");
}
}


Добавление и изменение значений вручную

JsonObject user = new JsonObject();
user.addProperty("name", "Alice"); // Добавление строки
user.addProperty("age", 25); // Добавление числа
user.addProperty("isActive", true); // Добавление булева значения

// Добавление массива
JsonArray languages = new JsonArray();
languages.add("Java");
languages.add("Python");
user.add("languages", languages);

// Добавление вложенного объекта
JsonObject address = new JsonObject();
address.addProperty("city", "London");
address.addProperty("country", "UK");
user.add("address", address);

user.addProperty("age", 26); // Перезаписываем age

System.out.println(new Gson().toJson(user));


Преобразование между JsonElement и Java-объектами

Использование fromJson и toJsonTree

Из JSON в POJO (fromJson)
Gson gson = new Gson();
String json = "{\"name\":\"Bob\",\"age\":40}";

// Прямое преобразование строки в объект
Person person = gson.fromJson(json, Person.class);
System.out.println(person.getName()); // Bob

// Если есть JsonElement, можно использовать его
JsonElement jsonElement = JsonParser.parseString(json);
Person personFromElement = gson.fromJson(jsonElement, Person.class);


#Java #middle #Gson #JsonElement #JsonObject #JsonArray
Преобразование между JsonElement и Java-объектами

Использование fromJson и toJsonTree

Из JSON в POJO (fromJson)
Gson gson = new Gson();
String json = "{\"name\":\"Bob\",\"age\":40}";

// Прямое преобразование строки в объект
Person person = gson.fromJson(json, Person.class);
System.out.println(person.getName()); // Bob

// Если есть JsonElement, можно использовать его
JsonElement jsonElement = JsonParser.parseString(json);
Person personFromElement = gson.fromJson(jsonElement, Person.class);


Из POJO в JsonElement (toJsonTree)

Person person = new Person("Bob", 40);
JsonElement personElement = gson.toJsonTree(person);

// Теперь можно модифицировать JSON
if (personElement.isJsonObject()) {
JsonObject personObject = personElement.getAsJsonObject();
personObject.addProperty("email", "bob@example.com");
}

String modifiedJson = gson.toJson(personElement);
System.out.println(modifiedJson);


Как конвертировать JsonElement обратно в POJO
JsonObject userJson = new JsonObject();
userJson.addProperty("name", "Eve");
userJson.addProperty("age", 28);

// Преобразование JsonObject в POJO
Gson gson = new Gson();
Person person = gson.fromJson(userJson, Person.class);
System.out.println(person.getName()); // Eve


Полезные советы

Проверка isJsonNull() перед чтением значений
JsonElement element = jsonObject.get("optionalField");
if (element != null && !element.isJsonNull()) {
String value = element.getAsString();
}


Обработка разных типов полей
JsonElement dynamicField = jsonObject.get("dynamicField");
if (dynamicField.isJsonPrimitive()) {
JsonPrimitive primitive = dynamicField.getAsJsonPrimitive();
if (primitive.isString()) {
// Обработка строки
} else if (primitive.isNumber()) {
// Обработка числа
}
} else if (dynamicField.isJsonArray()) {
// Обработка массива
}


Использование JsonParser для разбора строки

JsonElement parsed = JsonParser.parseString(jsonString);


Создание сложных JSON структур
JsonObject response = new JsonObject();
JsonArray items = new JsonArray();

JsonObject item1 = new JsonObject();
item1.addProperty("id", 1);
item1.addProperty("name", "Item 1");

items.add(item1);
response.add("items", items);
response.addProperty("count", 1);

String jsonOutput = gson.toJson(response);


Эти методы позволяют гибко работать с JSON, когда точная структура неизвестна или требуется динамическая модификация данных.

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

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

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

Что то как-то неактивно! Неужто нет вопросов??? Пишите, все что не понятно! Не стесняемся! ✌️
Please open Telegram to view this post
VIEW IN TELEGRAM
Что выведет код?

public class Task230525 {
public static void main(String[] args) {
String str = " Hello ";
str = str.trim().replace('H', 'J').substring(1, 4);
System.out.println(str);
}
}


#Tasks