Java | Фишки и трюки
7.21K subscribers
182 photos
29 videos
6 files
40 links
Java: примеры кода, интересные фишки и полезные трюки

Купить рекламу: https://telega.in/c/java_tips_and_tricks

✍️По всем вопросам: @Pascal4eg
Download Telegram
⌨️ Text Blocks (Текстовые блоки)

В Java 15 появилась возможность задать константу типа String состоящую из нескольких строк без использования конкатенации.

Мы можем использовать текстовые блоки, объявив строку с """ (три двойные кавычки).

Это, безусловно, самый удобный способ объявления многострочной строки.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14👨‍💻2
Switch-выражения

Чтобы получить значение из switch-выражения, раньше приходилось создавать отдельную переменную и постоянно использовать break;.

В Java 14 появился новый формат записи, который помогает получать результат выбора и записывать выражение компактнее.

Если перечислены все возможные варианты, ветка default теперь не нужна.

Если в значение (case) нужно записать выражение, его заключают в фигурные скобки {} и для возврата значения используют ключевое слово yield.
👍10💯41
⌨️ try-with-resources

Благодаря конструкции "try-with-resources" вы можете элегантно и безопасно управлять ресурсами, такими как потоки, сокеты или другие объекты, требующие явного закрытия после использования. Это улучшение ввода-вывода позволяет автоматически закрывать открытые ресурсы после завершения блока try.

В блоке try может быть открыто несколько ресурсов и соответственно объявлено несколько переменных указывающих на них. Классы этих переменных должны реализовать интерфейс AutoCloseable.

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

try-with-resources доступен начиная с Java 7 и предоставляет удобный способ для обработки ресурсов и исключений, связанных с ними.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10🤓1🙈1
Netty - это мощный и высокопроизводительный фреймворк для разработки сетевых приложений на языке Java. Он предоставляет асинхронное и событийно-ориентированное программирование для создания масштабируемых сетевых приложений, таких как серверы, прокси, клиенты и другие.

Вот некоторые ключевые особенности Netty:

1⃣ Асинхронная и событийно-ориентированная модель: Netty предоставляет асинхронные API, которые позволяют обрабатывать большое количество одновременных соединений без блокирования. Событийно-ориентированный подход позволяет легко реагировать на различные события, такие как подключение клиента, чтение данных или отправка данных.

2⃣ Мультиплексирование: Netty поддерживает мультиплексирование, что позволяет обрабатывать множество соединений на одном потоке, что повышает производительность.

3⃣ Поддержка различных протоколов: Netty имеет гибкую архитектуру и поддерживает различные протоколы, такие как HTTP, WebSocket, TCP, UDP, SSL и многие другие.

4⃣ Высокая производительность: Netty разработан с акцентом на производительность и масштабируемость. Он широко используется в крупных сетевых приложениях, включая веб-серверы, чаты, игры и финансовые приложения.

5⃣ Простота использования: Несмотря на высокую производительность, Netty предоставляет чистый и интуитивно понятный API, который облегчает создание сетевых приложений.

6⃣ Поддержка технологий Java NIO и epoll: Netty использует возможности Java NIO и, в случае операционных систем, поддерживающих epoll, позволяет эффективно использовать их для оптимизации работы с сетью.

7⃣ Сообщество и документация: Netty имеет активное сообщество и обширную документацию, что делает его доступным для разработчиков и обеспечивает поддержку и обновления.

Netty является отличным выбором для разработчиков, которые хотят создавать высокопроизводительные и надежные сетевые приложения на платформе Java.
👍7😁21
😁16🤣7
⌨️ HashMap - это реализация интерфейса Map, которая представляет собой структуру данных, которая позволяет хранить пары ключ-значение и обеспечивает эффективный доступ к значениям по ключу. HashMap основан на хеш-таблице, что позволяет достигать высокой производительности при операциях вставки, удаления и поиска элементов. Вот как это работает:

1⃣ Вставка элемента:
При вставке элемента в HashMap, вы передаете ключ и значение. Сначала вычисляется хеш-код ключа с использованием метода hashCode(). Затем этот хеш-код преобразуется в индекс внутреннего массива (бакета) с помощью функции хеширования (обычно путем выполнения операции % на размере массива). Если в соответствующем бакете уже есть элементы, то новый элемент может быть добавлен в виде связанного списка или более сложной структуры данных, в зависимости от реализации HashMap.

2⃣ Поиск элемента:
Для поиска значения по ключу, вы передаете ключ методу get(). Здесь снова вычисляется хеш-код ключа и определяется индекс бакета. Затем HashMap проверяет все элементы в этом бакете, чтобы найти соответствующий ключ. Если есть несколько элементов с одинаковым хеш-кодом (коллизия), они могут быть проверены последовательно, пока не будет найден элемент с соответствующим ключом.

3⃣ Удаление элемента:
При удалении элемента по ключу, HashMap также вычисляет хеш-код ключа и находит соответствующий бакет. Затем элемент удаляется из этого бакета. Если в бакете есть несколько элементов, они могут быть перебраны для поиска правильного элемента.

Важно отметить, что хеширование и коллизии могут повлиять на производительность HashMap. Хорошая реализация должна уметь эффективно обрабатывать коллизии, чтобы обеспечить быстрый доступ к элементам.

HashMap также автоматически увеличивает свою емкость, когда количество элементов в нем превышает определенный порог, чтобы уменьшить вероятность коллизий и сохранить высокую производительность.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍16💩2👏1🤮1
Внедрение зависимостей (Dependency Injection) — это шаблон проектирования, который способствует слабой связи между компонентами системы. С помощью внедрения зависимостей вы можете внедрять зависимости в класс вместо того, чтобы создавать их внутри класса, что снижает сложность и зависимости вашего кода.

Внедрение зависимостей также может сделать ваш код более гибким и простым для тестирования, что делает его ценным методом изучения для разработчиков Java.

Библиотек для внедрения зависимостей существует огромное множество, например: Dagger2, Guice, Weld. Ну и конечно в популярном фреймворке Spring так же есть встроенная поддержка dependency injection.
👍5🔥3
Default Methods in Interfaces

В отличие от обычных методов интерфейса, мы объявляем их с ключевым словом default в начале сигнатуры метода, и они предоставляют реализацию.

Причина, по которой в версию Java 8 включены методы по умолчанию, довольно очевидна.
В типичном проекте, основанном на абстракциях, где интерфейс имеет одну или несколько реализаций, если к интерфейсу добавляется один или несколько методов, все реализации также будут вынуждены их реализовать. В противном случае конструкция просто сломается.

Методы интерфейса по умолчанию — эффективный способ решения этой проблемы. Они позволяют нам добавлять в интерфейс новые методы, которые автоматически доступны в реализациях. Поэтому нам не нужно изменять реализующие классы.

Таким образом, обратная совместимость аккуратно сохраняется без необходимости рефакторинга разработчиков.

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

Однако когда дело доходит до обеспечения обратной совместимости с существующим кодом, методы по умолчанию являются хорошим компромиссом.
👍7🔥2🤔1
Reflection API в Java предоставляет средства для анализа и манипуляции классами, методами, полями и другими элементами программы во время выполнения. Это позволяет программам получать информацию о структуре классов и объектов, вызывать методы, создавать экземпляры классов и даже изменять их состояние во время выполнения. Reflection API является мощным инструментом, но также может быть опасным и требует осторожного использования.

Вот некоторые основные элементы Reflection API:

Class класс: Основной класс для работы с Reflection API. Он представляет информацию о типе класса, интерфейса, массива или примитива. Вы можете получить объект Class для любого класса с использованием оператора class или вызвав метод getClass() на объекте.

Field класс: Позволяет получать информацию о полях класса и устанавливать их значения. Вы можете получить список полей класса и получать или устанавливать значения этих полей.

Method класс: Позволяет получать информацию о методах класса и вызывать их во время выполнения. Вы можете получить список методов класса, передать аргументы и вызвать методы.

Constructor класс: Позволяет получать информацию о конструкторах класса и создавать новые экземпляры объектов.

Package класс: Позволяет получать информацию о пакетах, к которым относится класс.

Reflection API может быть полезным, например, при создании библиотек или фреймворков, которые должны работать с классами, о которых они заранее не знают. Однако следует быть осторожным при использовании Reflection API, так как неправильное использование может привести к ошибкам во время выполнения и ухудшить производительность программы.
👍9🔥31
Множественная реализация интерфейсов с одинаковыми методами по умолчанию

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

В этом случае код просто не скомпилируется, так как возникает конфликт, вызванный множественным наследованием интерфейсов. Класс унаследует оба набора методов по умолчанию. Так какой же вызовется?

Чтобы решить эту двусмысленность, мы должны явно предоставить реализацию методов. Мы также можем заставить наш класс использовать методы по умолчанию одного из интерфейсов или всех сразу.
👍10🔥2
instanceof в Java 16

Чтобы проверить, к какому классу относится объект, используют оператор instanceof. Если нужно проверить объект и привести его к нужному классу, раньше писали условие с instanceof, объявляли переменную проверяемого типа и присваивали ей проверяемый объект, предварительно приведя его к проверяемому классу.

Начиная с Java 16 присвоение не требуется. Значение переменной можно задать прямо в выражении instanceof, дописав имя переменной после проверяемого типа.

📌 Если уловие построено с отрицанием, то новая переменная будет доступна вне блока условия.
👍11🔥1
Запечатанные классы

Sealed class дословно переводится как «запечатанный класс». В этом классе нужно сразу объявить список классов-наследников, потому что кроме них наследников быть не может.

Классы наследники должны быть в том же пакете или модуле, что и класс предок с модификатором sealed. Кроме этого, у них обязательно должен быть один из модификаторов:

final, если класс запрещён к дальнейшему наследованию

sealed, если наследование допустимо, но с заранее указанным списком наследников

non-sealed, когда для класса нужно снять любые ограничения по наследованию

У интерфейсов тоже может быть модификатор sealed.

Запечатанные классы помогают установить ограничение на число наследников, когда их набор определён и его не собираются часто менять.
👍92😍1
Forwarded from Цитата дня
🔥123😢3👨‍💻2🤡1
@Value Spring annotation

Эту аннотацию можно использовать для ввода значений в поля в bean-компонентах, управляемых Spring, и ее можно применять на уровне поля или параметра конструктора/метода.

Заполним наш application.properties файл:
value.from.file=Value got from the file
priority=high
listOfValues=A,B,C


Первый и самый бесполезный вариант использования это указать просто строку в аннотации @Value, эта строка и установится как значение аннотируемого члена класса.

Используя конструкцию ${propname} в аннотации, можно получить значение из конфигурационного файла приложения или переменной окружения.

Если значения может не быть, то можно определить значение по умолчанию ${unknown.param:some default}, если этого не сделать, то получим ошибку java.lang.IllegalArgumentException: Could not resolve placeholder 'unknown.param' in value "${unknown.param}"
👍5🔥3
💎 Запуск java приложения в Docker

Для запуска приложения в докере понадобится установленный Docker и приложение собранное в jar файл.

Для создания docker образа (image), на основе которого будет создаваться контейнер с вашим приложением, нужен файл с именем Dockerfile.

В этом файле должны быть 3 простые директивы:

FROM: указывает родительский образ, из которого мы создаем свой.

ADD: копируем jar файл внутрь образа

ENTRYPOINT: запуск команды после старта контейнера

Далее нужно собрать образ командой:
docker build -t my-java-app .

И запустить контейнер на основе созданного образа:
docker run -p 8080:8080 my-java-app

Эта команда запустит контейнер, привяжет порт 8080 в контейнере к порту 8080 на хосте и запустит ваше Java-приложение внутри контейнера.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥12👍6🐳5
QueryDSL — это мощный и чрезвычайно гибкий инструмент для работы с БД и просто подарок для Java-разработчиков, которые не очень хорошо разбираются в SQL (или совсем не разбираются), поскольку позволяет работать с БД при помощи привычного объектного представления сущностных зависимостей.

Querydsl был создан как замена громоздкого и многословного Criteria Query API.

Достоинства:

👉 типобезопасные запросы

👉 статическая проверка запросов
👍20👌1
Конвертировать InputStream в String

В Java-приложениях довольно часто требуется получить строку из входного потока, полученного, например, из файла или по сети.
🔥7👍3👎1
Часто в Java-приложении есть необходимость хранить файлы. И если приложение состоит из нескольких микросервисов, которым нужен доступ к файлам, то не обойтись без централизованного файлового хранилища. Одним из таких хранилищ является MinIO.

MinIO - это open source хранилище данных, совместимое с Amazon S3. Он обеспечивает отказоустойчивость, масштабируемость, шифрование данных и предоставляет богатые клиентские библиотеки для интеграции в приложения.

MinIO становится популярным выбором для хранения и управления данными благодаря своей гибкости и совместимости с Amazon S3, что делает его подходящим для широкого спектра приложений, от простых хранилищ данных до сложных облачных сценариев.
👍6🔥3🤗1
ACID (Atomicity, Consistency, Isolation, Durability) - это набор свойств, которые определяют стандарты для транзакций в базах данных. Эти свойства обеспечивают надежность и целостность данных в базе данных, даже в случае сбоев системы или непредвиденных ситуаций. Давайте рассмотрим каждое из этих свойств более подробно:

1⃣ Атомарность (Atomicity): Это свойство гарантирует, что транзакция будет выполнена полностью или не будет выполнена вовсе. Она является неделимой единицей работы, и либо все её операции будут успешно завершены, либо ни одна из них. Если хотя бы одна операция в транзакции завершится неудачно, все изменения, внесенные этой транзакцией, будут отменены (откат).

2⃣ Согласованность (Consistency): Это свойство обеспечивает, что только допустимые данные могут быть записаны в базу данных. Транзакция не должна нарушать целостность данных и бизнес-правила. Если транзакция приводит к недопустимому состоянию данных, она будет отменена.

3⃣ Изолированность (Isolation): Изоляция гарантирует, что одна транзакция не влияет на другие транзакции, выполняющиеся параллельно. То есть, каждая транзакция должна работать так, как будто она выполняется в изоляции от других транзакций. Это предотвращает конфликты и гарантирует, что данные не будут испорчены параллельными операциями.

4⃣ Долговечность (Durability): Долговечность означает, что изменения, внесенные в базу данных в рамках успешно завершенной транзакции, должны быть сохранены даже в случае сбоя системы или перезапуска. Другими словами, данные, записанные в базу данных, должны быть стойкими к сбоям и не должны теряться.

📌 Соблюдение этих четырех принципов ACID является критически важным для обеспечения надежности и целостности данных в системах управления базами данных (СУБД). Эти принципы позволяют гарантировать, что даже в сложных сценариях, таких как сбои системы или конфликты параллельных транзакций, данные останутся в согласованном и надежном состоянии.
👍15🆒21🔥1
Скачать файл используя Java NIO

Пакет Java NIO предлагает возможность передавать байты между двумя каналами без их буферизации в памяти приложения.

Чтобы прочитать файл по нашему URL-адресу, мы создадим новый ReadableByteChannel из потока URL-адреса.

Байты, прочитанные из ReadableByteChannel, будут переданы в FileChannel, соответствующий загружаемому файлу.

Используем метод transferFrom() из класса ReadableByteChannel для загрузки байтов с заданного URL-адреса в наш FileChannel.

Методы transferTo() и transferFrom() более эффективны, чем простое чтение из потока с использованием буфера. В зависимости от операционной системы данные могут быть перенесены непосредственно из кэша файловой системы в наш файл без копирования каких-либо байтов в память приложения.

В системах Linux и UNIX эти методы используют метод нулевого копирования, который уменьшает количество переключений контекста между режимом ядра и пользовательским режимом.
👍15🔥1