Java Geek
2.5K subscribers
256 photos
1 file
16 links
Практичные советы, лайфхаки и код для Java-разработчиков. Каждый пост — реальная польза. Учим Java на примерах.

По всем вопросам @evgenycarter
Download Telegram
Почему Map не наследуется от Collection?

Это связано с тем, что Map представляет отображение ключ-значение, в то время как Collection представляет коллекцию объектов.

Коллекции работают с объектами на основе их позиции в коллекции, тогда как в Map объекты доступны по ключу. Поэтому операции, определенные в Collection, такие как добавление, получение по индексу и итерация, не имеют смысла для Map.

Вместо этого в Map определены операции для работы с парами ключ-значение, такие как put(), get(), containsKey() и другие. Наследование Map от Collection привело бы к наследованию неподходящих методов.

👉 @java_geek
Создание подклассов исключений

Для того чтобы создать класс собственного исключения, достаточно определить его как производный от класса Exception.

В подклассах собственных исключений совсем не обязательно реализовать что-нибудь. В самом классе Exception не определено никаких методов.

Зачастую указывать описание исключения непосредственно при его создании очень удобно, но иногда для этого лучше переопределить метод toString().

👉 @java_geek
ListIterator

ListIterator — это интерфейс итератора, предназначенный специально для работы со списками.

В отличие от обычного Iterator, ListIterator позволяет не только итерировать список в прямом направлении, но и в обратном.
Он поддерживает операции для перемещения вперед и назад по списку.

ListIterator реализует методы:
— next(): переход к следующему элементу.
— previous(): переход к предыдущему элементу.
— hasNext(): проверка, есть ли следующий элемент.
— hasPrevious(): проверка, есть ли предыдущий элемент.
— add(): добавление элемента в список.

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

👉 @java_geek
Может ли метод принимать аргументы переменной длины?

В Java метод может принимать переменное количество аргументов двумя основными способами:

— Используя массив в качестве параметра. При определении метода указывается, что один из параметров — это массив некоторого типа. При вызове метода в этот параметр можно передать массив нужной длины.

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

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

👉 @java_geek
ByteBuffer

ByteBuffer используется для работы с байтовыми данными.
Он позволяет читать и записывать байты в буфер в памяти.

Основные способы использования:
— Чтение/запись байтовых данных из файлов, сетевых соединений и других источников. ByteBuffer обеспечивает эффективный доступ к данным без копирования.

— Преобразование между байтами и другими типами данных как примитивными (int, float), так и объектными. Можно получить доступ к байтам объекта или записать объект в байтовое представление.

— Компактное хранение данных в оперативной памяти. ByteBuffer располагается в памяти даже в случае больших объемов данных.

— Обработка байтовых данных как потока байт. Можно последовательно читать или записывать данные в буфер.

— Доступ к данным «по смещению» без копирования. Можно получить «вид» на часть буфера.

👉 @java_geek
StringBuilder

StringBuilder — это класс для работы с изменяемыми строками, аналогичный StringBuffer. API класса StringBuilder такой же, как у StringBuffer, он также хранит строку в виде модифицируемого массива символов.

Но, в отличие от StringBuffer, StringBuilder не является потокобезопасным. Он работает быстрее за счет отсутствия синхронизации.
Поэтому его рекомендуется использовать в однопоточных приложениях для работы со строками, когда нет необходимости в синхронизации.

При создании можно задать начальную емкость buffer'а в виде размера массива символов.
Если строка превышает текущую емкость, она автоматически расширяется с сохранением содержимого.

👉 @java_geek
Что такое finalize? Зачем он нужен?

finalize() — это метод, который вызывается перед уничтожением объекта сборщиком мусора в Java.

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

Финализатор может быть полезен, когда нужно гарантировать, что объект освободит какие-то ресурсы даже в случае, если программист забыл явно вызвать метод закрытия ресурсов.
Однако, на практике лучше не полагаться на него, так как неизвестно, когда именно сборщик мусора вызовет его.
Поэтому рекомендуется явно освобождать ресурсы с помощью try-finally блоков.

👉 @java_geek
Selector

Класс Selector используется для организации многоканального неблокирующего ввода-вывода.
Основная идея в том, что Selector позволяет одному потоку следить за состоянием множества каналов (сокетов, файловых каналов) и обрабатывать их события (готовность к чтению/записи).

Возможности Selector:
— Регистрация множества каналов в Selector для мониторинга.
— Проверка готовности зарегистрированных каналов к операциям чтения, записи.
— Извлечение готовых каналов и выполнение операций с ними.
— Отмена регистрации каналов в Selector.

Использование Selector позволяет избежать блокировки на операциях чтения/записи по каналам и эффективно масштабировать приложение для одновременной работы с большим количеством соединений.
Класс часто применяется в сетевых серверах для неблокирующей обработки большого числа клиентских соединений в одном потоке.

👉 @java_geek
CompletableFuture

CompletableFuture в пакете java.util.concurrent является классом, который предоставляет мощный и гибкий подход к асинхронному программированию. Он позволяет выполнять асинхронные операции и обрабатывать их результаты, комбинировать несколько операций и управлять зависимостями между ними.

Помимо операций, представленных на изображении, CompletableFuture также предоставляет множество других методов для работы с асинхронными операциями, таких как thenApply(), thenCompose(), thenCombine(), exceptionally() и другие, которые позволяют обрабатывать результаты, комбинировать операции, обрабатывать исключения и многое другое. Это делает CompletableFuture мощным инструментом для асинхронного программирования.

👉 @java_geek
Кэширование

Кэширование (caching) — это механизм хранения временных данных в оперативной памяти или на диске, чтобы улучшить производительность приложения. Кэширование позволяет избежать повторного вычисления или запроса данных, которые уже были получены или рассчитаны ранее.

👉 @java_geek
Sorted set

SortedSet — это интерфейс в Java Collection Framework, который предоставляет упорядочение элементов в множестве. Элементы упорядочиваются с помощью их естественного порядка или с помощью компаратора, который обычно предоставляется при создании отсортированного множества.

SortedSet имеет несколько дополнительных операций, которые позволяют использовать упорядочение элементов:
— first() и last() возвращают первый и последний элементы в множестве соответственно.
— headSet(), tailSet() и subSet() возвращают подмножества элементов, которые находятся до, после или между заданными элементами соответственно.

В этом примере мы создаем TreeSet (класс, который реализует SortedSet) и добавляем в него несколько строк. Поскольку строки реализуют интерфейс Comparable, они упорядочиваются в алфавитном порядке. Затем мы используем различные методы SortedSet для получения первого и последнего элементов, а также подмножеств элементов.

👉 @java_geek
Метод valueOf()

Метод valueOf() используется для преобразования различных типов данных в объекты класса String.
Он определен во многих встроенных классах обертках примитивных типов, таких как Integer, Double, Boolean и других.

Основные преимущества использования valueOf():

— Преобразование примитивных типов в объекты обертки для использования в Collections.
— Удобное преобразование числовых типов в строки.
— Получение объектного представления примитивного значения.

В примере создается целочисленная переменная i со значением 10. Далее метод Integer.valueOf(i) преобразует int в объект Integer. После чего вызывается метод toString() у объекта Integer, который возвращает строковое представление числа.

👉 @java_geek
Почему нельзя объявить метод интерфейса с модификатором final или static?

Причина, по которой в интерфейсах нельзя объявлять методы с модификаторами final или static заключается в следующем:

Final методы предназначены для того, чтобы классы-наследники не могли их переопределить. Но если метод интерфейса объявить финальным, это нарушит саму суть интерфейсов — предоставить общий набор методов для реализации в других классах.

Static методы принадлежат классу, а не отдельным объектам этого класса. Описывая метод в интерфейсе мы имеем в виду, что он должен быть реализован в классах и вызываться у объектов этих классов. Статические же методы не предназначены для реализации и вызова на экземплярах класса, поэтому static методы в интерфейсах тоже не имеют смысла.

👉 @java_geek
Абстракция в Java

Абстракция — это способность выделять существенные характеристики объекта и упускать несущественные.
Абстракция позволяет сосредоточиться на важных свойствах и поведении объекта, скрыв детали реализации.

В Java абстракция реализуется с помощью абстрактных классов и интерфейсов.

Абстрактный класс содержит абстрактные методы без реализации. Подклассы обязаны реализовать эти методы.
Интерфейс задает «контракт», описывая поведение классов без деталей реализации. Классы реализуют интерфейс.

Реализация абстракции требует тщательного анализа предметной области и выделения общих свойств объектов.

👉 @java_geek
В каком случае требуется переопределять метод service()?

Метод service() переопределяется, когда необходимо, чтобы сервлет обрабатывал все запросы (и GET, и POST) в одном методе.

Когда контейнер сервлетов получает запрос клиента, то происходит вызов метода service(), который в зависимости от поступившего запроса вызывает или метод doGet() или метод doPost().

👉 @java_geek
Класс LocalDateTime

Класс LocalDateTime используется для работы с датой и временем без учета часового пояса.
Он появился в Java 8 в пакете java.time и является частью новой date/time API, которая пришла на смену устаревшим классам Date и Calendar.

Основные возможности класса LocalDateTime:
— Хранение даты и времени с точностью до наносекунд.
— Получение различных компонентов даты/времени (год, месяц, день недели и т. д.).
— Выполнение операций сложения и вычитания дат и интервалов.
— Сравнение и сортировка дат по времени.
— Форматирование и парсинг строк по заданному шаблону.

👉 @java_geek
Контейнер Optional

Optional — это контейнер, который может содержать какое-то значение или не содержать ничего.
Он используется для обозначения отсутствия значения вместо null. Это позволяет избежать ошибок NullPointerException.

Optional появился в Java 8. Он представлен классом java.util.Optional.
Чтобы создать экземпляр Optional, используются статические методы:
— empty() для пустого Optional.
— of() для Optional с заданным значением.

Для получения значения из Optional используются методы get(), или orElse() с указанием значения по умолчанию. Также есть методы фильтрации значений, например filter(), map() и flatMap().

👉 @java_geek
Класс java.util.Date

Класс java.util.Date представляет дату и время. Date хранит дату и время в миллисекундах с 1 января 1970 года 00:00:00 по UTC.

Конструкторы Date() и Date(long date) позволяют создать объект Date с текущей датой/временем или указанной датой/временем в миллисекундах.

Методы getTime() и setTime(long time) позволяют получить и установить время в миллисекундах.

Методы как getDay(), getMonth() и т. д. позволяют получить отдельные компоненты даты/времени.

Методы before() и after() позволяют сравнивать даты.

👉 @java_geek
Как получить синхронизированную коллекцию из не синхронизированной?

Для того, чтобы получить синхронизированную коллекцию из несинхронизованной, можно использовать несколько способов:

— Обернуть исходную коллекцию в Collections.synchronizedList/Set/Map. Это создаст обёртку, которая будет синхронизировать все операции с коллекцией.

— Использовать один из классов синхронизированных коллекций из java.util.concurrent. При создании экземпляра этих классов, коллекция уже будет синхронизирована.

— Создать собственную реализацию коллекции, в которой явно синхронизировать методы с помощью synchronized или Lock.

— Использовать коллекцию, которая синхронизируется внутри каким-либо образом, например Vector.

👉 @java_geek
Gradle

Это инструмент автоматизации сборки, который в основном используется в Android-разработке. Популярная альтернатива Ant и Maven.

Gradle позволяет определять и управлять зависимостями проекта, запускать модульные тесты и упаковывать приложение для развертывания. Gradle также имеет систему плагинов, которая позволяет добавлять функциональные возможности и настраивать процесс сборки.

👉 @java_geek
CompletableFuture

CompletableFuture — это класс в Java, введенный в Java 8, который представляет собой асинхронную задачу, которая будет выполнена в будущем и возвращает результат. CompletableFuture предоставляет множество методов для работы с асинхронными задачами, комбинирования их и управления их выполнением.

Основные возможности CompletableFuture включают:

— Вы можете запустить задачу асинхронно и продолжить выполнение кода без блокировки.
— CompletableFuture позволяет комбинировать результаты нескольких задач, выполняя определенные действия при завершении каждой задачи.
— Вы можете указать обработчики ошибок для обработки исключений, возникающих во время выполнения задачи.
— Вы можете блокировать выполнение кода и ждать завершения задачи.

👉 @java_geek