Библиотека Java разработчика
📚 Лайфхаки, приёмы и лучшие практики для Java-разработчиков. Всё, что ускорит код и прокачает навыки. Java, Spring, Maven, Hibernate. По всем вопросам @evgenycarter РКН clck.ru/3KoGeP
Ko'proq ko'rsatish📈 Telegram kanali Библиотека Java разработчика analitikasi
Библиотека Java разработчика (@bookjava) Rus til segmentidagi kanali faol ishtirokchi. Hozirda hamjamiyat 10 264 obunachidan iborat bo'lib, Texnologiyalar & Aralashmalar toifasida 12 013-o'rinni va Rossiya mintaqasida 63 881-o'rinni egallagan.
📊 Auditoriya ko‘rsatkichlari va dinamika
невідомо sanasidan buyon loyiha tez o‘sib, 10 264 obunachiga ega bo‘ldi.
12 Iyun, 2026 dagi oxirgi ma’lumotlarga ko‘ra kanal barqaror faollikka ega. Oxirgi 30 kunda obunachilar soni 8 ga, so‘nggi 24 soatda esa 1 ga o‘zgardi va umumiy qamrov yuqori darajada qolmoqda.
- Tasdiqlash holati: Tasdiqlanmagan
- Jalb etish (ER): Auditoriya o‘rtacha 8.51% darajada jalb etiladi. Nashrdan keyingi dastlabki 24 soatda kontent odatda umumiy obunachilar sonining 4.36% ini tashkil etuvchi reaksiyalarni to‘playdi.
- Post qamrovi: Har bir post o‘rtacha 873 marta ko‘riladi; birinchi sutkada odatda 447 ta ko‘rish yig‘iladi.
- Reaksiyalar va o‘zaro ta’sir: Auditoriya faol: har bir postga o‘rtacha 6 ta reaksiya keladi.
- Tematik yo‘nalishlar: Kontent string, интерфейс, строка, boot, api kabi asosiy mavzularga jamlangan.
📝 Tavsif va kontent siyosati
Muallif resursni shaxsiy fikrni ifoda etish maydoni sifatida ta’riflaydi:
“📚 Лайфхаки, приёмы и лучшие практики для Java-разработчиков. Всё, что ускорит код и прокачает навыки. Java, Spring, Maven, Hibernate.
По всем вопросам @evgenycarter
РКН clck.ru/3KoGeP”
Yuqori yangilanish chastotasi (oxirgi ma’lumot 13 Iyun, 2026 da olingan) sababli kanal doimo dolzarb va katta qamrovli bo‘lib qoladi. Analitika auditoriya kontent bilan faol hamkorlik qilishini, uni Texnologiyalar & Aralashmalar toifasidagi muhim ta’sir nuqtasiga aylantirishini ko‘rsatadi.
final, либо закройте доступ наследникам ко всем способам мутации, перечисленным в следующих пунктах;
2. Сделайте все поля финальными;
3. Не выставляйте наружу методов-мутаторов, которые меняют состояние;
4. Не отдавайте наружу поля ссылочного изменяемого типа (объекты классов, массивы) – если объект под ссылкой не иммутабельный, должна возвращаться его глубокая копия (defensive copy);
5. Создавайте объект правильно (подробнее в следующем посте).
Если вам нужны преимущества иммутабельного объекта, но также нужно иногда изменять его, подойдет подход copy on write: каждый метод-мутатор должен мутировать и возвращать не сам объект, а только что созданную его копию. Оригинал всё так же остается неизменным.
#Классы
👉@BookJavaError как и любой другой Throwable можно поймать в блок catch. Такой код абсолютно валидный и скомпилируется без проблем.
На практике, согласно спецификации, значение исключения типа Error – необрабатываемая ошибка, ловить которую нет смысла.
Более того, выброс исключения подтипа VirtualMachineError означает, что JVM находится в сломанном состоянии. Дальнейшая работа непредсказуема: OutOfMemoryError приводит к невозможности создания новых объектов, StackOverflowError теряет фреймы стека вызова, и так далее.
Так как ловить Error не нужно, объявление её в секции throws сигнатуры метода необязательно. Как и RuntimeException, Error – разновидность unchecked exception.
#Язык #JVM
👉@BookJavaarraycopy(), наоборот, максимально гибкий – позволяет копировать часть массива и указывать массив, в который копировать.
Arrays.copyOf(), Arrays.copyOfRange() и все их перегрузки. Утилитарные методы, которые дают более специализированные способы копирования. Внутри все используют System.arraycopy().
Копирование через стрим. Arrays.stream(sourceArray).toArray(). Удобно когда нужно встроить дополнительные промежуточные операции.
Сторонними библиотеками. Обычно обеспечивают дополнительные удобства, такие как проверка корректности параметров, приведения типов, и прочие. Пример – класс SerializationUtils из Apache Commons.
Все перечисленные способы создают поверхностную копию – оба массива в итоге ссылаются на одни и те же объекты. Лучший способ создать глубокую копию – реализовать ее вручную. Сначала оператором new создается пустой массив нужного размера, затем в цикле заполняется копиями элементов. Stream API здесь может дать удобный интерфейс реализации, и оптимизировать копирование с помощью многопоточности.
Самый быстрый, но ужасный по эффективности способ глубокого копирования массива без реализации копирования отдельных элементов – сериализация+десериализация. Сложно придумать оправдание такому плохому способу для продакшна, но этот метод вполне подходит для реализации быстрого прототипа, или для тестового кода.
#Язык
👉@BookJavaObject[] можно попытаться положить любой объект в любой массив:
Object x[] = new String[3];
x[0] = new Integer(0);
Компилятор гарантирует, что когда вы берете элемент из массива, он будет представителем типа элементов самого этого массива. Не важно какого типа переменная его хранит. Именно для обеспечения этой гарантии работает проверка типа времени выполнения, которая и выбрасывает ArrayStoreException.
Ситуация похожа на проблему heap pollution в случае дженериков. Только для этого случая такая проблема возникает реже, потому что работает проверка этапа компиляции:
// Ошибка компиляции – дженерики инвариантны!
List<Object> x = new ArrayList<String>();
#Дженерики
👉@BookJavaclass Foo<T> на generic параметре T невозможно выполнить никакой оператор: нельзя взять его .class, нельзя применить его в instanceof. Также и вызов на нем оператора new приведет к ошибке.
Причина этих ограничений кроется в стирании типов. Дженерик параметры правильно воспринимать скорее как ограничения типов, чем как конкретные типы. Эти ограничения действуют для более строгих проверок на этапе компиляции. В рантайме же информация о конкретных переданных типах-параметрах стирается. А все эти операторы выполняются именно в рантайме.
Стандартный простой способ действия здесь – кроме значения типа T передавать еще и объект-дескриптор для этого типа, экземпляр класса Class<T>. Объект может быть создан из дескриптора рефлекшеном.
Но существует один хак, способный справиться со стиранием типов. Тип-параметр все-таки остается в одном месте в рантайме. Метод метакласса наследника определившего конкретный тип getGenericSuperclass() возвращает класс, которым параметризован родитель.
#Классы #Дженерики
👉@BookJavaMap в том, что в отличие от других коллекций инициализация должна принять параметрами набор пар неопределенного размера. Поэтому varargs здесь не подходит.
Самый примитивный, многословный, но простой способ – добавить элементы сразу после создания. Для мапы-поля класса это можно сделать в конструкторе или блоке инициализации.
Map<String, String> map = new HashMap<>();
{
map.put("one", "first");
map.put("two", "second");
}
Идиома double brace initialization. Компактная запись, которая расшифровывается компилятором как создание анонимного класса-наследника от HashMap, с добавлением элементов в блоке статической инициализации. Создание нового класса приводит к дополнительным накладным расходам, так делать не рекомендуется.
new HashMap<String, String>() {{
put("one", "first");
put("two", "second");
}};
Для специальных случаев, пустой и одноэлементной неизменяемых мап, в классе Collections есть соответствующие фабричные методы emptyMap() и singletonMap(key, value).
Удобно создавать HashMap из стрима. Коллектор Collectors.toMap(keyMapper, valueMapper) с помощью мапперов превратит объекты потока в ключи и значения.
В Java 9 наконец появились фабричные метод Map.of(), перегруженный для разного количества пар параметров, и Map.ofEntries() с varargs-аргументом.
До Java 9 подобное было реализовано во многих популярных библиотеках, например ImmutableMap.of в Guava и MapUtils.putAll() в Apache Commons.
#Коллекции
👉@BookJava@Vаlue. Все поля класса будут финализированы и сделаны приватными.
👉@BookJavaVector синхронизированы, а ArrayList - нет;
• По умолчанию, Vector удваивает свой размер, когда заканчивается выделенная под элементы память. ArrayList же увеличивает свой размер только на половину.
Vector это устаревший класс и его использование не рекомендовано.
👉@BookJavaparallel(). Некоторые стримы создаются уже многопоточными, например результат вызова Collection#parallelStream(). Для распараллеливания используется единый общий ForkJoinPool.
Внутри реализации потока его сплиттератор оборачивается в AbstractTask, который и отправляется на выполнение в пул. AbstractTask при выполнении считывает estimateSize сплиттератора и текущую степень параллелизма пула. На основе этих данных он принимает решение, распараллелить ли сплиттератор на два методом trySplit().
У удобства такого решения есть обратная сторона. Так как пул единый, нагрузка распределяется на всех пользователей параллельных стримов в программе. Если в одном потоке выполняются долгие блокирующие операции, это может ударить по производительности в совершенно не связанном с ним другом потоке.
Если всё же требуется использовать отдельный пул потоков, сам стрим выполняется как задача этого отдельного пула. Подробнее в статье.
#Классы #Многопоточность
👉@BookJava
Endi mavjud! Telegram Tadqiqoti 2025 — yilning asosiy insaytlari 
