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

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

Наш канал на RUTube - https://rutube.ru/channel/37896292/
Download Telegram
Что такое Lock и чем он лучше synchronized? 🤓

Ответ:

Интерфейс Lock (например, ReentrantLock) предоставляет более гибкую синхронизацию, чем synchronized.

Поддерживает тайм-ауты (tryLock), неблокирующие операции и возможность прерывания.

Пример:

Lock lock = new ReentrantLock();
lock.lock();
try {
// Критическая секция
} finally {
lock.unlock();
}

В отличие от synchronized, Lock требует явного вызова unlock().

#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
📌 Факт дня:

А вы знали, что первый компьютерный "контроллер версии" был создан в 1972 году?

Первыми системами контроля версий были SCCS (Source Code Control System) и RCS (Revision Control System). SCCS была разработана в 1972 году в Bell Labs и стала первой системой, которая позволяла отслеживать изменения в исходном коде. Эта система использовала простую модель хранения изменений, что делало её удобной для небольших проектов. RCS, появившаяся в 1982 году, улучшила функциональность SCCS и стала более популярной благодаря своей простоте и эффективности. RCS использовала концепцию "ревизий" и позволяла легко переключаться между различными версиями кода.


Proof

#facts
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
📌 Цитата дня: Виктор Орловский

"Технологии без доверия пользователей — пустой звук."


Виктор Орловский, бывший CTO Сбербанка, сказал это в 2018 году на fintech-конференции в Москве.


Биография

#Citation #Biography
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Null - отсутствие ссылки в Java

null в Java — это специальное зарезервированное значение, указывающее, что переменная-ссылка не указывает ни на один объект. Это важный элемент модели памяти Java, отражающий отсутствие объекта. null может быть присвоен любой переменной ссылочного типа: объекту, массиву, строке, интерфейсу и т.д.

Что такое null

Когда вы пишете:
String name = null;


Вы создаёте переменную name, которая не указывает на какой-либо объект в куче. Это эквивалентно "пустой" ссылке. Она существует, занимает место в стеке (как любая переменная), но не ссылается на объект в памяти.

Зачем нужен null

Обозначение "ничего"
Позволяет явно указать, что у переменной нет значения. Это особенно полезно, если объект должен быть присвоен позже или вычисляется по условию.


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

Все ссылки в Java по умолчанию равны null, если не инициализированы вручную.
public class Example {
String name; // По умолчанию null
}


Маркер отсутствия
null часто используется как сигнал того, что результат не найден, произошла ошибка, или объект ещё не готов.

Как работает null в памяти
Ссылочные переменные (например, Person person) хранятся в стеке.
Когда переменной присваивается null, это означает, что в ячейке стека отсутствует указатель на объект в куче.
Сам объект в куче при этом не создаётся или уже был уничтожен сборщиком мусора, если на него больше нет ссылок.

Person person = null;


Здесь:
person — ячейка в стеке
Значение этой ячейки — специальное значение null (в JVM это просто 0 в ссылке)


Примеры использования
String userInput = null; // Пользователь ничего не ввёл

if (userInput == null) {
System.out.println("Пустой ввод");
}

List<String> list = getList();
if (list != null) {
list.add("new item");
}


Плюсы использования null

Простота и ясность
Читабельный способ выразить "ничего", не создавая лишние объекты.

Низкие накладные расходы
Не требует выделения памяти в куче, что экономит ресурсы при инициализации.

Совместимость с другими системами
Многие API и базы данных возвращают null как знак "отсутствия значения".

Минусы и подводные камни

1. NullPointerException
Наиболее распространённая ошибка в Java — попытка вызвать метод или поле на null:
String name = null;
System.out.println(name.length()); // NullPointerException


2. Неочевидность
Программа может работать "нормально", пока в какой-то момент не возникнет null в неожиданном месте. Это затрудняет отладку.

3. Проблемы при композиции
Методы, возвращающие null, требуют дополнительных проверок в вызывающем коде:
String result = compute();
if (result != null) {
...
}
Если забыть такую проверку — возможна ошибка.


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

Лучшие практики и альтернативы

Явная проверка на null
Objects.requireNonNull(input, "Input must not be null");


Использование Optional
Optional<String> result = Optional.ofNullable(getName());
result.ifPresent(System.out::println);
Optional помогает избежать null, особенно в возвращаемых значениях.


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

Лучше избегать null, когда можно:
List<String> list = new ArrayList<>(); // вместо null


Контракты "никогда не null"
В современных проектах стараются придерживаться соглашения: параметры, возвращаемые значения и поля по умолчанию не null, если явно не сказано иное.

Специальные случаи и нюансы

Сравнение с null
if (obj == null) { ... }


Всегда используйте ==, а не equals() для сравнения с null.
obj.equals(null); // Может выбросить NPE, если obj == null


Ссылочные типы и null

Массивы: могут быть null, отдельные элементы массива — тоже.

Строки: null — не то же самое, что пустая строка "".

String s1 = null;
String s2 = "";
System.out.println(s1 == s2); // false


Метод instanceof и null

String s = null;
System.out.println(s instanceof String); // false


null в параметрах
Вы можете передать null как аргумент в метод:
printName(null);
Но важно, чтобы метод корректно это обрабатывал.


#Java #для_новичков #beginner #reference_types #null
👍4
Forwarded from ChatRoom (Java for Beginner) (Первожрец Java)
А есть еще желающие активно поучаствовать в учебной разработке приложения на Spring? Пишите! 😉
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥1
Что выведет код?

public class Task240625 {
public static void main(String[] args) {
String s = null;
s = s + "Java";
System.out.println(s);
}
}


#Tasks
👍3
Продолжаем выбирать темы для разбора и голосовать за рассмотрение предложенных! 🤓

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

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

Не стесняемся! ✌️
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Что такое deadlock и как его избежать? 🤓

Ответ:

Deadlock (взаимная блокировка) возникает, когда два или более потока ждут друг друга для освобождения ресурсов.

Пример:
поток A ждет ресурс X, удерживая Y, а поток B ждет Y, удерживая X.

Избежать можно:
- Упорядочивая захват ресурсов.
- Используя тайм-ауты (tryLock в Lock).
- Минимизируя области синхронизации.

Пример упорядочивания:

synchronized (resource1) {
synchronized (resource2) {
// Работа с ресурсами
}
}

#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
📌 Факт дня:

А вы знали, что термин "пиксель" был придуман в 1965 году?

Термин «пиксель» впервые появился в научной литературе в 1965 году благодаря Фредерику Биллингсли[3], сотруднику лаборатории реактивного движения. Он использовал это слово для обозначения графических компонентов в видеоданных, полученных с космических аппаратов, исследовавших Луну и Марс. Однако авторство термина принадлежит не Биллингсли. Он заимствовал его у Кита Макфарленда из компании Link Division of General Precision в Пало-Алто, который, в свою очередь, утверждал, что слово уже было в обиходе около 1963 года
.


proof

#facts
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
📌 Цитата дня: Евгений Чичваркин

"Интернет — это свобода, но свобода требует ответственности."

Евгений Чичваркин, сооснователь Евросети, сказал это в 2008 году в интервью о развитии e-commerce в России.

Биография

#Citation #Biography
Please open Telegram to view this post
VIEW IN TELEGRAM
Руководство по POM (Project Object Model) в Maven

POM (Project Object Model) является основой любого Maven-проекта. Файл pom.xml определяет структуру проекта, его зависимости, процесс сборки и другие аспекты, необходимые для управления жизненным циклом проекта. Этот документ представляет собой XML-файл, который Maven интерпретирует для создания модели проекта в памяти.


Основные теги

Основные теги pom.xml формируют базовую идентификацию и структуру проекта. Они обязательны или критически важны для корректной работы Maven.

<project>: Корневой элемент каждого pom.xml. Он определяет пространство имен XML (xmlns) и схему (xsi:schemaLocation), чтобы Maven мог валидировать файл. Все остальные элементы являются дочерними для <project>. В памяти Maven создает объект Project, который хранит всю информацию о проекте, включая зависимости, плагины и настройки сборки.
<modelVersion>: Указывает версию модели POM, используемой в файле. На момент 2025 года стандартной является версия 4.0.0. Этот тег необходим, так как Maven использует его для определения правил парсинга и совместимости. Неправильная версия приведет к ошибке парсинга.
<groupId>: Уникальный идентификатор группы, к которой относится проект. Обычно это доменное имя компании или организации в обратном порядке (например, com.example). В памяти Maven использует groupId как часть координат для идентификации артефакта в репозитории.
<artifactId>: Уникальное имя артефакта внутри группы. Это название проекта или модуля (например, my-app). Вместе с groupId и version формирует уникальные координаты артефакта.
<version>: Версия проекта. Следует семантическому версионированию (например, 1.0.0-SNAPSHOT). Maven использует версию для управления артефактами в локальном и удаленных репозиториях. Суффикс SNAPSHOT указывает на нестабильную версию, что влияет на поведение кэширования.
<packaging>: Определяет тип выходного артефакта (например, jar, war, pom). По умолчанию — jar. Этот тег влияет на жизненный цикл сборки, так как Maven выбирает соответствующие плагины и цели (goals) для обработки. Например, для war подключается плагин maven-war-plugin.

Эти теги формируют минимальный pom.xml. Maven парсит их в объектную модель, которая хранится в памяти JVM во время выполнения. Объектная модель включает org.apache.maven.model.Model, где каждый тег маппится на соответствующее поле или коллекцию. Например, groupId, artifactId и version объединяются в уникальный ключ артефакта.


Расширенные теги

Расширенные теги добавляют метаданные, улучшающие документацию и управление проектом. Они необязательны, но полезны в корпоративных средах.

<name>: Человекочитаемое название проекта. Используется в отчетах и документации, генерируемых Maven (например, через maven-site-plugin). Не влияет на логику сборки, но хранится в метаданных артефакта.
<description>: Описание проекта. Как и <name>, используется для документации. Maven включает это поле в метаданные артефакта, которые публикуются в репозиторий.

<url>: URL проекта, например, сайт или репозиторий. Используется в документации и для генерации ссылок в отчетах.

<inceptionYear>: Год создания проекта. Это поле чисто информационное, хранится в метаданных.

<organization>: Содержит информацию об организации, включая <name> и <url>. Используется для единообразной документации в крупных проектах.

Эти теги не влияют на процесс сборки, но добавляются в файл метаданных артефакта (META-INF/maven/groupId/artifactId/pom.properties), который создается при упаковке. В памяти они хранятся как часть объекта Model, но не участвуют в логике выполнения.

#Java #middle #Maven #pom
👍3
Работа с <properties>

Тег <properties> позволяет определять пользовательские переменные, которые можно использовать в других частях pom.xml. Это улучшает читаемость и упрощает управление конфигурацией.

Пример:
<properties>
<java.version>11</java.version>
<spring.version>5.3.10</spring.version>
</properties>


Переменные используются через синтаксис ${property.name}.

Например:

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>


Maven при парсинге pom.xml заменяет все ${...} на соответствующие значения. Это происходит на этапе создания модели в памяти. Если свойство не найдено, Maven пытается использовать системные свойства JVM или переменные окружения. Если и это не удается, сборка завершится ошибкой.

Свойства также могут быть переопределены через командную строку:
mvn clean install -Djava.version=17


В памяти свойства хранятся в объекте Properties внутри модели Model. Они доступны всем плагинам и процессам сборки.
Важный нюанс: свойства не наследуются автоматически в дочерних модулях, если они определены в <properties> родительского POM. Для этого нужно использовать <dependencyManagement> или <pluginManagement>.


<dependencies>: Управление зависимостями

Тег <dependencies> определяет библиотеки, необходимые проекту. Каждая зависимость описывается тегом <dependency> с обязательными полями groupId, artifactId и version.

Scope'ы зависимостей

Атрибут <scope> определяет область применения зависимости:
compile: Зависимость доступна для компиляции, тестирования и выполнения. Включается в итоговый артефакт (например, в jar). Это значение по умолчанию.
provided: Зависимость нужна для компиляции, но предоставляется средой выполнения (например, сервлет API в контейнере). Не включается в итоговый артефакт.
runtime: Зависимость нужна только во время выполнения (например, JDBC-драйвер). Не используется при компиляции.
test: Зависимость нужна только для тестирования (например, JUnit). Не включается в итоговый артефакт.
system: Указывает локальный путь к зависимости через <systemPath>. Используется редко, так как нарушает принцип переносимости.
import: Используется в <dependencyManagement> для импорта зависимостей из другого POM. Не добавляет зависимость напрямую.


Maven при разрешении зависимостей создает граф зависимостей в памяти (используя org.apache.maven.artifact.Artifact). Для каждого артефакта хранится его scope, что влияет на classpath для различных фаз сборки. Например, test зависимости добавляются только в classpath для фазы test.

Exclusions и конфликт зависимостей

Конфликты зависимостей возникают, когда разные версии одной и той же библиотеки включаются через транзитивные зависимости. Maven решает конфликты, выбирая ближайшую к корню графа версию (стратегия "nearest wins"). Это может привести к проблемам, если выбранная версия несовместима.

Для исключения нежелательных транзитивных зависимостей используется тег <exclusions>:
<dependency>
<groupId>org.example</groupId>
<artifactId>lib-a</artifactId>
<version>1.0</version>
<exclusions>
<exclusion>
<groupId>org.unwanted</groupId>
<artifactId>unwanted-lib</artifactId>
</exclusion>
</exclusions>
</dependency>


В памяти Maven модифицирует граф зависимостей, удаляя исключенные артефакты. Это происходит на этапе разрешения зависимостей (dependency:resolve).

Для диагностики конфликтов полезна команда:
mvn dependency:tree


#Java #middle #Maven #pom
👍2
<dependencyManagement>: Централизованный контроль зависимостей

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

Пример:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.3.10</version>
</dependency>
</dependencies>
</dependencyManagement>


Зависимости из <dependencyManagement> не добавляются в проект автоматически. Они активируются только при указании groupId и artifactId в <dependencies> без версии. Это позволяет централизовать управление версиями в родительском POM.
В памяти Maven хранит эти зависимости в объекте DependencyManagement, который используется для разрешения версий при парсинге дочерних POM. Это снижает риск конфликтов версий в многомодульных проектах.
<build> и <plugins>
Тег <build> определяет процесс сборки проекта. Он включает настройки каталогов, плагинов и другие параметры.


Основные дочерние элементы:
<sourceDirectory>: Путь к исходному коду (по умолчанию src/main/java).
<testSourceDirectory>: Путь к тестам (по умолчанию src/test/java).
<resources>: Ресурсы, включаемые в артефакт.
<plugins>: Список плагинов для выполнения задач.


Пример плагина:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>11</source>
<target>11</target>
</configuration>
</plugin>


Каждый плагин привязан к фазам жизненного цикла Maven (например, compile, test, package). Плагины выполняются в JVM как отдельные классы, загружаемые через собственный класслоадер Maven. В памяти создается объект Plugin, содержащий конфигурацию и привязки к фазам.
Тег <pluginManagement> работает аналогично <dependencyManagement>, позволяя задавать конфигурацию плагинов для наследования в дочерних модулях.



<profiles>: Профили сборки

Профили позволяют настраивать сборку под разные окружения (например, dev, prod). Тег <profiles> содержит список <profile>.

Пример:
<profiles>
<profile>
<id>dev</id>
<properties>
<env>development</env>
</properties>
</profile>
<profile>
<id>prod</id>
<properties>
<env>production</env>
</properties>
</profile>
</profiles>


Профиль активируется через:
Командную строку: mvn clean install -Pdev.
Условия в <activation> (например, по OS, JDK или наличию файла).


Maven при парсинге объединяет активный профиль с основным pom.xml. Это происходит в памяти, где профиль мержится с моделью Model. Если несколько профилей активны, они применяются в порядке определения.
<repositories> и <pluginRepositories>

Теги <repositories> и <pluginRepositories> указывают, где Maven должен искать зависимости и плагины. По умолчанию используется центральный репозиторий Maven (https://repo.maven.apache.org/maven2).

Пример:
<repositories>
<repository>
<id>custom-repo</id>
<url>https://repo.example.com</url>
</repository>
</repositories>


Maven загружает артефакты сначала из локального репозитория (~/.m2/repository), затем из указанных репозиториев. В памяти создается список объектов Repository, которые используются резолвером зависимостей.

#Java #middle #Maven #pom
👍2
Parent POM'ы и наследование

Родительский POM позволяет централизовать конфигурацию для нескольких проектов.

Дочерний проект ссылается на родительский через <parent>:
<parent>
<groupId>com.example</groupId>
<artifactId>parent-project</artifactId>
<version>1.0</version>
</parent>


Maven при парсинге загружает родительский POM и объединяет его с дочерним.

Наследуются:
- <dependencyManagement> и <pluginManagement>.
- <properties>.
- <repositories> и <pluginRepositories>.

В памяти создается композитная модель Model, где дочерний POM имеет приоритет над родительским. Это позволяет переопределять настройки. Однако <dependencies> и <plugins> не наследуются напрямую, чтобы избежать нежелательных включений.


Нюансы работы в памяти

Maven при запуске создает в JVM объектную модель проекта:
Парсинг pom.xml с помощью библиотеки plexus-utils и создание объекта org.apache.maven.model.Model.
Разрешение переменных ${...} с учетом <properties>, системных свойств и окружения.
Построение графа зависимостей с использованием Aether (библиотека для работы с репозиториями).
Создание плана выполнения (execution plan), где плагины привязываются к фазам жизненного цикла.


Каждый плагин выполняется в изолированном класслоадере, чтобы избежать конфликтов зависимостей. Локальный репозиторий (~/.m2/repository) кэширует артефакты, минимизируя сетевые запросы. Для SNAPSHOT-версий Maven периодически проверяет обновления в удаленных репозиториях.



#Java #middle #Maven #Pom
👍2
Что выведет код?

import java.util.function.Consumer;

public class Task250625 {
public static void main(String[] args) {
Consumer<String> c1 = s -> System.out.print("A" + s);
Consumer<String> c2 = s -> System.out.print("B" + s);

c1.andThen(c2).accept("1");
c2.andThen(c1).accept("2");
}
}


#Tasks
👍2
Варианты ответа:
Anonymous Quiz
65%
A1B1B2A2
10%
A1B2A2B1
10%
A1B1A2B2
15%
B1A1B2A2
👍1
Что такое ThreadLocal? 🤓

Ответ:

ThreadLocal предоставляет каждой нити свою копию переменной, изолируя данные между потоками.

Полезно для хранения контекста, например, пользовательской сессии.

Пример:
ThreadLocal<Integer> threadId = ThreadLocal.withInitial(() -> Thread.currentThread().getId());
System.out.println(threadId.get());
// Уникальный ID для каждого потока

После использования нужно вызывать remove() для предотвращения утечек памяти.

#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
📌 Факт дня:

А вы знали, что около 15% электроэнергии в мире в 2025 году потребляют дата-центры?

Согласно отчету Международного энергетического агентства, к 2030 году потребление электроэнергии центрами обработки данных увеличится более чем вдвое и достигнет 945 ТВт·ч, что сопоставимо с годовым потреблением Японии. Основная причина роста — искусственный интеллект, на который в 2024 году уже приходилось 15% от общего энергопотребления дата-центров.


Proof

#facts
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
📌 Цитата дня: Павел Дуров

"Конфиденциальность — это право, а не привилегия."


Павел Дуров, основатель Telegram, сказал это в 2014 году в посте о миссии компании.


Биография

#Citation #Biography
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Автоупаковка и автораспаковка типов в Java

Java разделяет примитивные типы (int, boolean, char и др.) и ссылочные типы (в том числе классы-обертки Integer, Boolean, Character и т.д.). Чтобы упростить работу с обертками, Java (начиная с версии 1.5) ввела механизм автоупаковки (autoboxing) и автораспаковки (unboxing) — автоматическое преобразование между примитивами и их объектными аналогами.


Автоупаковка (Autoboxing)

Это автоматическое преобразование примитива в объект соответствующего класса-обертки.

Пример:
Integer x = 5; // int -> Integer автоматически


Java компилятор сам преобразует это в:

Integer x = Integer.valueOf(5);



Автораспаковка (Unboxing)

Обратное преобразование — объект-обертка в примитив.


Пример:
int y = x; // Integer -> int автоматически


На самом деле компилятор превращает это в:
int y = x.intValue();



Как это работает в памяти


До автоупаковки
int x = 10;
Integer y = new Integer(x); // вручную

x — хранится в стеке, занимает 4 байта.
y — объект в куче, содержит поле типа int со значением 10 и дополнительную информацию (например, hashCode, class pointer и т.д.).


С автоупаковкой
Integer z = 10;
Компилятор заменит это на Integer.valueOf(10), что использует кэш оберток от -128 до 127.


Примеры использования
List<Integer> numbers = new ArrayList<>();
numbers.add(10); // int -> Integer (autoboxing)
int n = numbers.get(0); // Integer -> int (unboxing)
Это работает, потому что ArrayList хранит только объекты, а int автоматически упаковывается и распаковывается.



Зачем нужна автоупаковка

Унификация с коллекциями
List<Integer> list = new ArrayList<>();
list.add(42); // без ручного создания new Integer(42)


Удобство синтаксиса


Писать проще и чище:
Integer sum = 0;
for (int i = 0; i < 10; i++) {
sum += i; // автораспаковка и автоупаковка
}


Обратная совместимость
Автоупаковка позволяет использовать новые коллекции с примитивами, не ломая старый код.


Подводные камни

1. NullPointerException
Автораспаковка объекта, равного null, вызывает исключение:
Integer x = null;
int y = x; // NullPointerException


2. Производительность
Автоупаковка создает лишние объекты, особенно в циклах:
Integer sum = 0;
for (int i = 0; i < 1000; i++) {
sum += i; // каждый шаг — распаковка, сложение, упаковка
}


Альтернатива:
int sum = 0; // быстрее и без накладных расходов


3. Сравнение ссылок

Integer a = 1000;
Integer b = 1000;
System.out.println(a == b); // false


А вот:
Integer a = 100;
Integer b = 100;
System.out.println(a == b); // true — значения из кэша


Потому что:
Integer.valueOf(...) кэширует значения от -128 до 127.
== сравнивает ссылки, а не значения.


4. Неявное создание объектов

Может вызвать нагрузку на сборщик мусора, если упакованные значения активно создаются и исчезают, особенно в многопоточной среде.

Разбор кэширования (Integer Cache)
Integer x = 127;
Integer y = 127;
System.out.println(x == y); // true

Integer x = 128;
Integer y = 128;
System.out.println(x == y); // false
Причина — кэш для Integer в диапазоне [-128; 127].


Это реализовано внутри Integer.valueOf():
public static Integer valueOf(int i) {
if (i >= -128 && i <= 127)
return IntegerCache.cache[i + 128];
else
return new Integer(i);
}



Практические советы

Используйте примитивы, если нет необходимости в объектах (например, в счетчиках, математике).
Избегайте упаковки в горячих циклах, особенно в производительном коде.
Будьте осторожны с null — автораспаковка null всегда приведет к ошибке.
Для сравнения используйте equals(), а не ==.


#Java #для_новичков #beginner #reference_types #Autoboxing #Unboxing
👍2