Секреты Java
Відкрити в Telegram
Обсуждаем Java, архитектуру, фреймворки и всё, о чем должны говорить разработчики. Владелец: @Alexey_Morl Реклама на бирже: https://telega.in/c/java_secrets
Показати більше7 991
Підписники
Немає даних24 години
Немає даних7 днів
Немає даних30 день
Архів дописів
7 991
✅OutOfMemoryError в Java не всегда говорит, что у вас переполнена память в Heap. Существует несколько видов OutOfMemoryError, и каждый из них указывает на определенную проблему:
▫️Java heap space: Этот тип ошибки, действительно, возникает, когда не хватает памяти в куче Java (Java heap) для создания новых объектов.
▫️PermGen space: Если приложение динамически загружает или создает большое количество классов, PermGen space может быть заполнена.
▫️Metaspace: Metaspace - это замена PermGen space в Java 8 и выше. Ошибка Metaspace возникает, когда JVM не может выделить достаточно памяти для хранения метаданных.
▫️Requested array size exceeds VM limit: Эта ошибка возникает, когда программа создает массив слишком большого размера
▫️GC overhead limit exceeded: Когда сборка мусора начинает потреблять слишком много времени и ресурсов.
▫️unable to create new native thread: Если программа создает слишком много потоков и не освобождает от них память.
▫️request size bytes for reason. Out of swap space? - Ошибка возникающая при проблемах с выделением памяти для приложения на стороне операционной системы.
🫡 Секреты Java
#outofmemory
7 991
✅Порядок инициализации полей класса
При проектировании классов, содержащих различные типы полей и блоков, важно помнить о порядке их инициализации.
В Java порядок инициализации следующий:
▫️Статические поля и статические блоки класса Parent в порядке объявления
▫️Статические поля и статические блоки класса Child в порядке объявления
▫️Поля и блоки инициализации экземпляра класса Parent в порядке объявления
▫️Конструктор класса Parent
▫️Поля и блоки инициализации экземпляра класса Child в порядке объявления
▫️Конструктор класса Сhild
🫡 Секреты Java
#class #constructor
7 991
✅Модификатор volatile
Ключевое слово
volatile в Java представляет собой модификатор переменной, который указывает, что переменная будет хранится в оперативной памяти.
public class SharedObject {
public volatile int value = 0;
}
Проблема видимости переменных
Из соображений производительности при работе приложения поток копирует переменные из оперативной памяти в кэш CPU, т.к. он быстрее. Если ваш компьютер содержит более одного CPU, потоки при выполнении могут использовать разные процессоры. А это значит, что каждый поток будет копировать переменные в кэш своего CPU.
Без ключевого слова volatile нет гарантии в какой момент JVM считает данные из основной памяти в кэш процессора, и когда запишет данные из кэша в память. Проблема появляется когда несколько потоков считают одну переменную из памяти и начнут с ней работать, при этом разные потоки не увидят изменение это переменной в кэше разных CPU.
При объявлении переменной volatile она будет считываться и записываться непосредственно в оперативную память, что гарантирует видимость записи другим потокам.
Когда модификатора volatile не достаточно?
Когда несколько потоков изменяют одну переменную и значение volatile переменной вычисляется на основе предыдущего (пример - увеличение значения). В этом случае короткий промежуток времени между чтением и записью значения переменной может привести к "race condition" (состоянии гонки)
Когда volatile достаточно?
Когда только один поток читает и пишет значение в volatile переменную, а другие потоки только читают. Либо когда новое значение записываемое в переменную volatile не зависит от старого.
Тем не менее чтение и запись в voltile переменную обходиться "дороже" по производительности, поэтому используйте их только когда необходимо обеспечить видимость данных.
🫡 Секреты Java
#multithreading7 991
✅Для чего нужна команда git cherry-pick?
Команда
git cherry-pick - мощный и удобный инструмент в системе контроля версий Git.
В отличие от команд merge и rebase, которые приводят к переносу всех коммитов объединяемых веток, эта команда позволяет взять один или несколько коммитов из одной ветки и применить их к другой ветке.
Когда это может быть полезно?
▫️При параллельной разработке в нескольких ветках может случится так, что вам необходим какой-либо компонент из соседней ветки. С помощью cherry-pick вы можете выбрать нужный коммит и перенести изменения
▫️Если был обнаружен баг, который необходимо срочно исправить не дожидаясь релиза. Разработчик может сделать исправления и залить этот коммит в основную ветку.
Чтобы использовать git cherry-pick, вам нужно знать идентификатор коммита, который вы хотите применить. Вы можете найти идентификатор коммита, просмотрев историю коммитов с помощью команды git log.
Пример:
Представим репозиторий со следующими ветками
a - b - c - d master
\
e - f - g feature
1. Переходим в master
git checkout master
2. Выполним перенос коммита
git cherry-pick <f_commitSHA>
где <f_commitSHA> - идентификатор коммита f
Результат:
a - b - c - d - f master
\
e - f - g feature
Чтобы перенести изменения, но не создавать коммит выполните команду:
git cherry-pick <commitSHA> -n
Если нужно перенести не один, а несколько идущих подряд коммитов:
git cherry-pick <start-commitSHA>...<end-commitSHA>
🫡 Секреты Java
#git7 991
✅Single Responsibility Principle
SOLID - мнемонический акроним, который был определен Робертом Мартином в 2000-х и который обозначает пять основных принципов проектирования и разработки легко обслуживаемого ООП кода.
SRP - Single Responsibility Principle или "Принцип единственной отвественности"
Много раз я слышал определение, что этот принцип о том, что одна функция/класс должны быть ответственны только за одну задачу. Вроде бы все верно, по крайней мере ассоциации с названием, которые приходят в голову, именно такие.
Но вот что говорит сам автор этих принципов:
"Класс должен иметь одну и только одну причину для изменений"Вот еще:
"Объединяйте вместе то, что меняется по одним и тем же причинам. Разделяйте то, что меняется по разным причинам"Можно ли однозначно понять о чем говорят эти определения? Сам автор писал, что столкнулся с неправильным пониманием этого принципа и попытался решить эту проблему дав новое определение в одной из своих книг:
"Модуль должен отвечать за одного и только за одного актора", где актор - это группа из одного или нескольких лиц заинтересованных в данном изменении. Тут стоит отметить, что в этот раз он говорит о модуле, а не о классе, имея ввиду, что SRP применим на различных уровнях. Для лучшего понимания представим простой пример, который нарушает SRP:
public class Employee {
int reportHours() { ... }
}
В нашей системе есть сотрудник и два актора, которые обращаются к методу reportHours():
▫️Бухгалтерия для подсчета заработной платы
▫️HR-отдел для каких то своих целей
В один момент у сотрудников появляется возможность работать сверхурочно, и бухгалтерия просит поменять алгоритм функции, чтобы сверхурочные часы считались х2. HR-отдел такие изменения точно не обрадуют!
Именно бизнес контекст определяет правильное распределение "ответственности".
🫡 Секреты Java
#solid7 991
✅ HashMap: принципы работы
HashMap в Java является одной из самых распространенных структур данных. Она позволяет хранить пары ключ-значение и обеспечивает быстрый доступ к данным. В Java класс HashMap находиться в пакете
java.util и реализует интерфейс Map.
Принципы работы:
▫️HashMap хранит данные в обычном массиве, где каждый элемент, называемый "bucket", содержит пару ключ-значение
▫️Для определения индекса bucket'а, куда будет помещена новая пара ключ-значения, используется функция hashCode() ключа
▫️При коллизии, когда два разных ключа имеют одинаковый хэш-код, HashMap использует метод equals(), чтобы проверить равенство ключей
▫️Если ключи равны по equals(), то старая пара ключ-значение заменяется на новую. Если ключи не равны, HashMap создает "цепочку" пар ключ-значений в bucket'е, которая реализуется на связанном списке или сбалансированном дереве
▫️Получение и удаление значений так же производится с использованием функций hashCode() и equals() ключа
Ключевым преимуществом использования HashMap перед другими типами Map является высокая эффективность функций put, get и remove, ведь средняя сложность этих операций константая O(1)
🫡 Секреты Java
#map #hashmap7 991
✅ Sealed классы
Sealed классы были представлены в Java 15. Эта функциональность дает возможность контролировать и ограничивать наследование от класса (либо интерфейса), явно указывая, кто может быть его наследниками.
Для того чтобы класс был sealed, он должен быть помечен ключевым словом
sealed. Также необходимо явно указать, какие классы могут быть его подклассами, с помощью ключевого слова permits.
Sealed класс накладывает три важных ограничения на его разрешенные подклассы:
▫️Все разрешенные подклассы должны принадлежать тому же модулю, что и sealed класс.
▫️Каждый разрешенный подкласс должен быть определен модификатором: final, sealed или non-sealed.
▫️Каждый разрешенный подкласс должен явно расширять sealed класс.
Для чего нам использовать sealed классы?
Одна из причин - это возможность автора кода повысить безопасность своих классов, защитив их от несанкционированного наследования.
🫡 Секреты Java
#java15