Java for Beginner
870 subscribers
1.01K photos
275 videos
14 files
1.69K links
Канал от новичков для новичков!
Изучайте Java вместе с нами!
Здесь мы обмениваемся опытом и постоянно изучаем что-то новое!

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

Наш канал на RUTube - https://rutube.ru/channel/37896292/
Download Telegram
Подход через кастомный коллектор (Java 8+)

Если teeing недоступен, реализуем Collector вручную:

public LibraryStatistics analyzeWithCustomCollector() {
return books.stream()
.collect(new LibraryStatsCollector());
}

private static class LibraryStatsCollector
implements Collector<Book, StatsAccumulator, LibraryStatistics> {

@Override
public Supplier<StatsAccumulator> supplier() {
return StatsAccumulator::new;
}

@Override
public BiConsumer<StatsAccumulator, Book> accumulator() {
return (acc, book) -> {
// Обновление Map авторов
acc.oldestByAuthor.merge(
book.getAuthor(),
book,
(a, b) -> a.getYear() < b.getYear() ? a : b
);

// Накопление страниц
acc.totalPages += book.getPages();

// Накопление для фантастики
if (book.hasGenre("Фантастика")) {
acc.fantasyCount++;
acc.fantasyPriceSum += book.getPrice();
}
};
}

@Override
public BinaryOperator<StatsAccumulator> combiner() {
return (left, right) -> {
// Слияние для параллельных потоков
left.oldestByAuthor.putAll(right.oldestByAuthor); // с разрешением
left.totalPages += right.totalPages;
left.fantasyCount += right.fantasyCount;
left.fantasyPriceSum += right.fantasyPriceSum;
return left;
};
}

@Override
public Function<StatsAccumulator, LibraryStatistics> finisher() {
return acc -> new LibraryStatistics(
acc.oldestByAuthor,
acc.totalPages,
acc.fantasyCount == 0
? OptionalDouble.empty()
: OptionalDouble.of(acc.fantasyPriceSum / acc.fantasyCount)
);
}

@Override
public Set<Characteristics> characteristics() {
return Collections.emptySet(); // не CONCURRENT из-за HashMap
}
}

private static class StatsAccumulator {
Map<String, Book> oldestByAuthor = new HashMap<>();
int totalPages = 0;
int fantasyCount = 0;
double fantasyPriceSum = 0.0;
}


Практические задания

Задача 1: реализовать оба способа
В проекте «Библиотека» создайте класс LibraryAnalyzer с методами:
analyzeThreePasses() — три отдельных Stream
analyzeOnePassTeeing() — через teeing (если Java 12+)
analyzeOnePassCustom() — через кастомный Collector
Протестируйте на 100, 10 000 и 100 000 книг. Измерьте время System.nanoTime().

Задача 2: добавить четвёртую агрегацию
Добавьте: Map<String, Long> — жанр → количество книг.
Обновите оба подхода. В кастомном коллекторе используйте Map.merge() для подсчёта.

Задача 3: параллельная версия
Модифицируйте кастомный коллектор: добавьте CONCURRENT в характеристики, замените HashMap на ConcurrentHashMap или используйте toConcurrentMap.
Сравните stream() vs parallelStream() для 1 000 000 книг на многоядерной машине.

Задача 4: ленивая статистика (звёздочка)
Реализуйте LazyLibraryStatistics — класс, который не вычисляет агрегации при создании, а при первом обращении к любому полю выполняет один проход и кэширует все результаты.
Используйте Supplier + AtomicReference для thread-safe ленивой инициализации.


#Java #для_новичков #beginner #stream_api #практика
👍5
Что выведет код?

import java.util.concurrent.*;

public class Task060326 {
public static void main(String[] args) throws InterruptedException {
CountDownLatch latch = new CountDownLatch(3);
CyclicBarrier barrier = new CyclicBarrier(3, () -> System.out.print("GO "));

for (int i = 0; i < 3; i++) {
new Thread(() -> {
try {
latch.countDown();
latch.await();
barrier.await();
} catch (Exception e) {}
}).start();
}

latch.await();
System.out.print("FINISH ");
}
}


#Tasks
👍2
Что такое CountDownLatch и CyclicBarrier? В чем разница? 🤓

Ответ:

Оба класса из java.util.concurrent используются для синхронизации потоков.

CountDownLatch — это счетчик, который уменьшается вызовом countDown(). Потоки, вызывающие await(), блокируются, пока счетчик не станет равен 0. Используется одноразово, например, когда один поток ждет завершения нескольких других.

CyclicBarrier — это барьер, который собирает потоки. Когда все потоки достигают барьера (вызывают await()), они одновременно освобождаются. Может быть повторно использован (cyclic). Используется, когда потоки ждут друг друга, чтобы начать новый этап работы.


#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
История технологий сегодня — 07 марта

ℹ️ Кто родился в этот день

Фрэнсис Элизабет «Бетти» Холбертон (7 марта 1917, Филадельфия, Пенсильвания — 8 декабря 2001, Роквилл, Мэриленд) — американский программист. Одна из первых шести программистов ENIAC — первого универсального электронного цифрового компьютера. Автор изобретения точки останова для отладки программ.


🌐 Знаковые события

1876 — Александр Белл получил патент на телефон.

1926 — установлена радиотелефонная связь между Лондоном и Нью-Йорком.

1997 — журнал «Nature» сообщил, что учёные из Рослинского института в Эдинбурге (Шотландия) воспроизвели ягнёнка без участия половых клеток барана. На свет появилась клонированная овца Долли.


#Biography #Birth_Date #Events #07марта
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
С 28.02 по 06.03
Предыдущий пост(с 21.02 по 27.02)

Воскресный мотивационный пост:
Не было мотивации

Запись встреч/видео:
8. Логирование и ELK-стек: как расследуют инциденты в production

Обучающие статьи:
Раздел 8. Stream API и функциональный стиль

Глава 4: Искусство агрегации. Коллекторы и группировки
Коллектор — это рецепт агрегации
groupingBy и многоуровневая агрегация
(Практика): Анализ библиотеки в один проход

Советы по Java:
[Совет по Java #011]
Тема: Random — потоконебезопасный и медленный для многопоточки.

[Совет по Java #012]
Тема: При итерации по Map для получения и ключа, и значения используйте entrySet(), а не keySet() с последующим get().



Полезные статьи и видео:
Модель памяти Java процесса

Как и всегда, задачи можно найти под тегом - #Tasks, вопросы с собеседований - #собеседование
👍3🔥1
Java for Beginner
Как вам первая фаза нашего OrderHub? Нравится?

Можно выбрать много вариантов.
Как всегда все те же голосуют))

Обнял - приподнял❤️
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
История технологий сегодня — 08 марта

💐 Международный женский день — праздник, который отмечается ежегодно 8 марта в ряде государств и стран мира.

Появился как день солидарности женщин в борьбе за женские права и эмансипацию. В 1945 году устав Организации Объединённых Наций стал первым международным документом, утвердившим принцип равенства мужчин и женщин. С 1977 года Международный женский день отмечается государствами-членами ООН.

Всех присутствующих на канале женщин поздравляю с праздником, желаю всегда оставаться обворожительными и незаменимыми 🌹


ℹ️ Кто родился в этот день

Отто Ган (нем. Otto Hahn — Отто Хан; 8 марта 1879, Франкфурт-на-Майне — 28 июля 1968, Гёттинген) — немецкий физик, учёный-новатор в области радиохимии, открывший ядерную изомерию (Уран Z) и расщепление урана. Получил Нобелевскую премию по химии за 1944 год. Гленн Сиборг назвал его «отцом ядерной химии».

Ральф Генри Бер (англ. Ralph Henry Baer; 8 марта 1922, Родальбен, Юго-западный Пфальц — 6 декабря 2014, Манчестер, Нью-Гэмпшир) американский изобретатель, разработчик видеоигр, инженер, предприниматель, получивший прозвище «Отец видеоигр» за свой огромный вклад в развитие этой индустрии, особенно в первые годы существования компьютерных игр как таковых. В 1956 году основал собственную компанию. В ней работали до 500 инженеров, которые занимались преимущественно военными заказами. Именно эта работа подала Беру идею, которая в итоге привела к созданию первой в мире игровой приставки.

Майкл Стерн Харт (англ. Michael Stern Hart; 8 марта 1947 — 6 сентября 2011)американский писатель, изобретатель электронных книг и основатель проекта «Гутенберг», который сделал электронные книги свободно доступными через Интернет. Большинство первых материалов он напечатал и разместил лично. В 1971 году Майкл Харт получил неограниченный доступ ко времени крупного компьютера Xerox Sigma V от операторов в университете штата Иллинойс. Пытаясь достойно применить этот ресурс, он создал первую электронную книгу Декларация независимости США, когда впечатал её текст в компьютер. Так путём создания электронных копий большего количества книг получил начало Проект «Гутенберг». Избегал расходов на врачей, предпочитая домашние средства. Собрал много компьютеров и стереосистем, другой аппаратуры, часто из вышедшего из употребления оборудования, жертвуя собственной роскошью ради борьбы с безграмотностью и сохранения доступа общественности к информационным ресурсам. Вёл жизнь, близкую к бедности, «питаясь, в основном, бобовыми консервами».


🌐 Знаковые события

1950 — СССР объявил о наличии атомной бомбы.

1979 — компания Philips представляет компакт-диск.

1979 — изображения, сделанные Вояджером-I, доказали существование вулканизма на Ио, спутнике Юпитера.


#Biography #Birth_Date #Events #08марта
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
История технологий сегодня — 09 марта


ℹ️ Кто родился в этот день

Ю́рий Алексе́евич Гага́рин (9 марта 1934, Клушино, Гжатский (ныне Гагаринский) район, Западная область (ныне — Смоленская область) — 27 марта 1968, возле села Новосёлово, Киржачский район, Владимирская область) — советский космонавт и военный лётчик, первый человек, совершивший космический полёт. Герой Советского Союза, кавалер высших знаков отличия ряда государств, почётный гражданин многих российских и зарубежных городов.

Го́вард Ха́тауэй Э́йкен (англ. Howard Hathaway Aiken; 9 марта 1900, Хобокен, штат Нью-Джерси, США — 14 марта 1973, Сент-Луис, штат Миссури, США)американский пионер компьютеростроения. В должности инженера IBM руководил работами по созданию первого американского компьютера «Марк I».

Эндрю Джеймс Витерби (англ. Andrew James Viterbi, имя при рождении Андреа Джакомо Витерби (итал. Andrea Giacomo Viterbi); род. 9 марта 1935 года, Бергамо, Королевство Италия)американский инженер и бизнесмен, сооснователь Qualcomm и разработчик алгоритма Витерби.


🌐 Знаковые события

1937 — Московский телецентр на Шаболовке осуществил первую в СССР опытную передачу электронного телевидения в эфир.

1948 — на циклотроне в Калифорнии удаётся получить мезоны.


#Biography #Birth_Date #Events #09марта
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
[Совет по Java #013]

Тема: Аннотация @Transactional не работает на private и protected методах. Spring использует AOP-прокси, которые не могут переопределить не-public методы.

Проблема: Многие разработчики ошибочно полагают, что достаточно поставить @Transactional над любым методом, и Spring магическим образом обеспечит управление транзакциями.

Однако механизм работы Spring Transactions основан на AOP-прокси (динамических прокси JDK или CGLIB-прокси). Прокси — это подкласс или реализация интерфейса целевого класса, который переопределяет публичные методы для добавления сквозной функциональности (открытие/закрытие транзакции).

Если метод помечен как private или protected, прокси не может его переопределить, и аннотация игнорируется. Метод выполняется без транзакционного контекста, что приводит к трудноотлавливаемым багам: данные сохраняются неполностью, отсутствует откат при исключениях, соединения не закрываются.

Решение: Всегда используйте @Transactional только на public методах.

Транзакционность должна применяться на уровне сервиса (фасада), а не на внутренних вспомогательных методах. Если вам нужно вызвать транзакционный метод из того же класса, используйте self-injection (внедрение ссылки на самого себя через @Autowired/@jakarta.inject.Inject) или выделите транзакционную логику в отдельный @Service-компонент. В Spring 4.3+ можно использовать @Autowired для внедрения прокси самого себя.

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.support.TransactionSynchronizationManager;

@Service
public class UserService {

@Autowired
private UserRepository userRepository;

@Autowired
private UserService selfProxy; // Self-injection для вызова из того же класса

//Антипаттерн: @Transactional на private методе
@Transactional
private void badPrivateMethod(User user) {
// Транзакции НЕ БУДЕТ! Метод не переопределяется прокси
userRepository.save(user);
if (user.getEmail() == null) {
throw new RuntimeException("Ошибка — отката не будет!");
}
}

//Правильно: public метод
@Transactional
public void goodPublicMethod(User user) {
userRepository.save(user);
if (user.getEmail() == null) {
throw new RuntimeException("Ошибка — транзакция откатится");
}
}

// Проблема внутреннего вызова
public void callInternal() {
User user = new User("John");
//Транзакции не будет — вызов напрямую, не через прокси
goodPublicMethod(user); // ФАКТИЧЕСКИ: this.goodPublicMethod()
}

//Решение: вызов через self-proxy
public void callCorrectly() {
User user = new User("John");
selfProxy.goodPublicMethod(user); // Вызов через прокси — транзакция работает
}
}

// Альтернативное решение: вынос логики в отдельный компонент
@Service
class InternalUserService {
@Transactional
public void doInTransaction(User user) {
// транзакционная логика
}
}

@Service
class MainUserService {
@Autowired
private InternalUserService internalService;

public void call() {
internalService.doInTransaction(new User("John")); // Транзакция работает
}
}


Объяснение: Spring создает прокси вокруг целевого бина.

При вызове метода через прокси сначала выполняется транзакционный перехватчик, который открывает транзакцию, затем вызывается оригинальный метод, после чего транзакция коммитится или откатывается. При вызове private метода прокси не участвует — вызов идет напрямую к целевому объекту (this). Self-injection решает эту проблему, заставляя обращаться к самому себе через прокси.

Важно понимать, что для работы @Transactional нужен публичный метод, управление транзакциями на уровне контейнера и правильная конфигурация прокси (по умолчанию — JDK dynamic proxy, требующий интерфейса, или CGLIB, работающий с классами).


#Java #советы
👍5
Что выведет код?

@SpringBootApplication
public class TransactionalTricky implements CommandLineRunner {

@Autowired
private UserService userService;

public static void main(String[] args) {
SpringApplication.run(TransactionalTricky.class, args);
}

@Override
public void run(String... args) {
userService.saveUser();
System.out.println(userService.getCounter());
}

@Service
static class UserService {
private int counter = 0;

@Transactional
public void saveUser() {
privateIncrement();
}

@Transactional
private void privateIncrement() {
counter++;
}

public int getCounter() {
return counter;
}
}
}


#Tasks
👍3
Варианты ответа:
Anonymous Quiz
24%
0
18%
1
53%
исключение
6%
зависание
👍4
Что такое ConcurrentHashMap и чем он лучше Hashtable? 🤓

Ответ:

ConcurrentHashMap
из пакета java.util.concurrent — это потокобезопасная реализация Map, оптимизированная для многопоточной среды.

В отличие от Hashtable, которая синхронизирует все методы (блокируя всю таблицу), ConcurrentHashMap использует более тонкую блокировку.

В Java 7 — сегментирование, в Java 8+ блокируются отдельные элементы корзины (или используется Compare-And-Swap). Это позволяет параллельно выполнять чтение и запись в разные сегменты/корзины. Он также не выбрасывает ConcurrentModificationException при итерации.


#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
История технологий сегодня — 10 марта

ℹ️ Кто родился в этот день

Евге́ний Ла́заревич Роша́л (род. 10 марта 1972, Челябинск) российский программист, автор файлового менеджера FAR Manager, формата сжатия RAR, архиваторов RAR и WinRAR.


🌐 Знаковые события

1977 — несколько групп астрономов США, Австралии, Индии, ЮАР открыли кольца Урана.

1982 — редкий парад планет — все девять планет (Меркурий, Венера, Земля, Марс, Юпитер, Сатурн, Уран, Нептун и Плутон) собрались по одну сторону от Солнца в секторе с углом 95 градусов (то есть, максимальная разность гелиоцентрических эклиптических долгот планет составила 95 градусов).

2006 — автоматическая межпланетная станция Mars Reconnaissance Orbiter достигла Марса.


#Biography #Birth_Date #Events #10марта
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Раздел 8. Stream API и функциональный стиль в Java

Глава 5: Контракты. Почему equals, hashCode и иммутабельность — закон

equals/hashCode в операциях distinct, groupingBy, toSet

Stream API не существует в вакууме. Он опирается на фундаментальные контракты Java-объектов, установленные классом Object: equals для логического сравнения, hashCode для хеширования, compareTo для упорядочивания.

Нарушение этих контрактов не всегда приводит к немедленным ошибкам компиляции или очевидным исключениям. Вместо этого порождаются "мистические" баги: данные исчезают, дублируются, группируются неправильно — и всё это проявляется недетерминированно, часто только под нагрузкой или при смене окружения.

Рассмотрим класс Book, разработанный без должного внимания к контрактам:
public class Book {
private final String title;
private final String author;
private final int year;

// Конструктор, геттеры
// equals и hashCode НЕ переопределены!
}


По умолчанию equals и hashCode наследуются от Object, реализуя идентичность по ссылке: два объекта равны только если это один и тот же экземпляр в памяти. Для доменной модели, где логическая эквивалентность определяется содержимым, это поведение некорректно.


groupingBy и распределение по бакетам

Коллектор groupingBy использует HashMap для организации групп. При добавлении элемента вычисляется хеш-код ключа, определяющий бакет (сегмент внутреннего массива HashMap). Если в бакете уже есть элементы, выполняется проверка equals для разрешения коллизий.

Проблема возникает при использовании ключа без корректного hashCode:
// Две логически идентичные книги
Book book1 = new Book("1984", "George Orwell", 1949);
Book book2 = new Book("1984", "George Orwell", 1949);

// Создаём поток с дублированием
List<Book> library = Arrays.asList(book1, book1, book2, book2);

// Группировка по книге как ключу
Map<Book, Long> countByBook = library.stream()
.collect(groupingBy(Function.identity(), counting()));

System.out.println(countByBook.size()); // Ожидаем 1, получаем...?


Без переопределённого hashCode book1 и book2 имеют разные хеш-коды (по умолчанию System.identityHashCode), вычисляемые из адресов памяти. Они попадают в разные бакеты HashMap. Внутри каждого бакета equals возвращает false, потому что сравнение по ссылке даёт отрицательный результат. Результат: две записи в Map вместо одной, счётчики показывают 2 для каждой "уникальной" книги.

Баг проявляется недетерминированно. При небольшом числе элементов HashMap может поместить оба объекта в один бакет случайно (из-за пересечения хешей по модулю размера таблицы), и equals обнаружит их различность, но коллизия разрешится корректно — повезло. При росте данных таблица расширяется, бакеты становятся уже, вероятность коллизии падает, баг становится стабильным. При смене JVM (разная версия, разная реализация Object.hashCode) хеш-коды меняются, и поведение меняется без изменения кода.


distinct: фильтрация дубликатов без гарантий

Операция distinct() использует LinkedHashSet для отслеживания уникальных элементов. Она полагается на тот же контракт equals/hashCode:
List<Book> uniqueBooks = library.stream()
.distinct()
.collect(toList());


Без корректных методов distinct не удаляет логические дубликаты, только ссылочные. Если book1 и book2 — разные объекты с одинаковым содержимым, оба попадут в результат. Память растёт, кэширование не работает.

Особенно опасно это в распределённых системах: объект десериализуется в разных узлах, создавая разные экземпляры в памяти. Без equals/hashCode по значению они воспринимаются как разные сущности.


toSet и потеря элементов

Collectors.toSet() возвращает HashSet, основанный на хеш-таблице. Некорректный hashCode ведёт к дублированию:
Set<Book> bookSet = library.stream()
.collect(toSet());

System.out.println(bookSet.size()); // Ожидаем 1, получаем 2


HashSet добавляет элемент, если в соответствующем бакете нет равного (по equals). Разные хеш-коды → разные бакеты → оба элемента добавлены. Множество перестаёт быть множеством.

#Java #для_новичков #beginner #stream_api #equals_hashCode
👍5
Иммутабельность ключей: бомба замедленного действия

Даже при корректных equals/hashCode опасность подстерегает в изменяемых ключах. Рассмотрим сценарий с составным ключом-автором:
public class Author {
private String name; // Не final! Сеттер есть!
private String country;

// equals и hashCode по всем полям
@Override public int hashCode() {
return Objects.hash(name, country);
}
}

// Группировка книг по автору
Map<Author, List<Book>> byAuthor = library.stream()
.collect(groupingBy(Book::author));

// Позже в коде...
Author key = byAuthor.keySet().iterator().next();
key.setName("Modified Name"); // Мутация ключа!

// Попытка доступа
List<Book> books = byAuthor.get(key); // null?!


HashMap хранит ключ в бакете, соответствующем хеш-коду на момент вставки. При изменении полей name или country hashCode объекта меняется, но позиция в таблице — нет. get(key) вычисляет новый хеш, ищет в другом бакете, не находит совпадения, возвращает null. Данные не потеряны физически (объект Author и список Book существуют в памяти), но недоступны через Map.

Это "утечка" памяти логического характера: структура данных разрастается, но поиск перестаёт работать. Баг проявляется далеко от места мутации, диагностика требует глубокого понимания работы хеш-таблиц.


Правильная реализация контрактов

Для Book корректные equals и hashCode должны учитывать все значимые поля:
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Book book = (Book) o;
return year == book.year &&
Objects.equals(title, book.title) &&
Objects.equals(author, book.author);
}

@Override
public int hashCode() {
return Objects.hash(title, author, year);
}


Ключевые требования к контракту:
Рефлексивность: x.equals(x) всегда true
Симметричность: x.equals(y) тогда и только тогда, когда y.equals(x)
Транзитивность: если x.equals(y) и y.equals(z), то x.equals(z)
Консистентность: многократные вызовы дают один результат (требует иммутабельности)
Согласованность с hashCode: равные объекты имеют равные хеш-коды
Последнее требование критично для HashMap/HashSet. Нарушение (equals true, но hashCode разный) делает коллекции неработоспособными.


Рекорды как решение

Java Records (14+, стабильно в 16+) автоматически генерируют корректные equals, hashCode, toString по всем компонентам, гарантируя иммутабельность:
public record Book(String title, String author, int year) {}

// Автоматически: final поля, конструктор, геттеры, equals, hashCode, toString


Использование records для ключей groupingBy, элементов distinct, элементов toSet устраняет класс ошибок, связанных с контрактами. Единственное ограничение: компоненты records также должны быть иммутабельными и с корректными контрактами. Если Author в Book — изменяемый класс, проблема сохраняется.


Диагностика в production


При подозрении на нарушение контрактов:
Логирование хеш-кодов: вывести System.identityHashCode(obj) и obj.hashCode() для "одинаковых" объектов. Различие указывает на проблему.
Проверка equals: убедиться, что obj1.equals(obj2) возвращает true для логически эквивалентных объектов.
Анализ мутаций: установить точки останова на сеттеры ключей, используемых в Map.
Использование LinkedHashMap/LinkedHashSet: сохраняют порядок вставки, облегчая отладку.

#Java #для_новичков #beginner #stream_api #equals_hashCode
👍7
Что выведет код?

import java.util.*;
import java.util.stream.Collectors;

public class Task100326 {
public static void main(String[] args) {
List<Item100326> items = Arrays.asList(
new Item100326(1, "A"),
new Item100326(1, "B"),
new Item100326(2, "C"),
new Item100326(2, "D")
);

Set<Item100326> set = new LinkedHashSet<>(items);

Map<Integer, List<Item100326>> grouped = items.stream()
.collect(Collectors.groupingBy(Item100326::getId));

System.out.print(set.size() + " ");
System.out.print(grouped.get(1).size() + " ");
System.out.print(grouped.get(2).get(0).getName());
}

static class Item100326 {
private int id;
private String name;

Item100326(int id, String name) {
this.id = id;
this.name = name;
}

public int getId() { return id; }
public String getName() { return name; }

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Item100326 item = (Item100326) o;
return id == item.id;
}

@Override
public int hashCode() {
return Objects.hash(id);
}
}
}


#Tasks
👍3
Варианты ответа:
Anonymous Quiz
11%
2 2 A
33%
4 2 C
44%
2 2 C
11%
4 2 A
👍3
Что такое аннотации (Annotations) и как создать свою? 🤓

Ответ:

Аннотации
— это форма метаданных, добавляемая в код (классы, методы, поля) для передачи информации компилятору, инструментам сборки или фреймворкам во время выполнения.

Они начинаются с @.

Стандартные аннотации:
@Override, @Deprecated, @SuppressWarnings.

Чтобы создать свою аннотацию, используют ключевое слово
@interface. Можно задать мета-аннотации: @Retention (когда доступна: SOURCE, CLASS, RUNTIME), @Target (к чему применять), @Inherited и др.

Аннотации могут содержать элементы (методы без параметров и тела).


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