Библиотека 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 265 obunachidan iborat bo'lib, Texnologiyalar & Aralashmalar toifasida 12 016-o'rinni va Rossiya mintaqasida 63 847-o'rinni egallagan.
📊 Auditoriya ko‘rsatkichlari va dinamika
невідомо sanasidan buyon loyiha tez o‘sib, 10 265 obunachiga ega bo‘ldi.
13 Iyun, 2026 dagi oxirgi ma’lumotlarga ko‘ra kanal barqaror faollikka ega. Oxirgi 30 kunda obunachilar soni 13 ga, so‘nggi 24 soatda esa 3 ga o‘zgardi va umumiy qamrov yuqori darajada qolmoqda.
- Tasdiqlash holati: Tasdiqlanmagan
- Jalb etish (ER): Auditoriya o‘rtacha 8.59% darajada jalb etiladi. Nashrdan keyingi dastlabki 24 soatda kontent odatda umumiy obunachilar sonining 4.32% ini tashkil etuvchi reaksiyalarni to‘playdi.
- Post qamrovi: Har bir post o‘rtacha 882 marta ko‘riladi; birinchi sutkada odatda 443 ta ko‘rish yig‘iladi.
- Reaksiyalar va o‘zaro ta’sir: Auditoriya faol: har bir postga o‘rtacha 7 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 14 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.
Serializable;
5. В методе writeReplace оригинального класса инстанциируется и возвращается прокси от this;
6. Симметричные действия совершаются для чтения – в классе-посреднике реализуется метод readResolve;
7. В основном классе добавляется readObject, который выбрасывает исключение – это защитит от чтения без прокси.
Пример кода реализации.
#СериализацияSerializable класса весь контроль над сериализацией достается JVM. С помощью определения специальных методов можно кастомизировать его части. Метод readObject при этом обычно начинается с вызова стандартной части сериализации – ObjectInputStream.defaultReadObject().
Интерфейс Externalizable расширяет Serializable и добавляет методы записи и чтения writeExternal и readExternal. Входной и выходной потоки-аргументы в них представлены более абстрактно чем в специальных методах – интерфейсами ObjectInput и ObjectOutput.
Этот интерфейс позволяет реализовать полностью свой механизм сериализации, стандартно запишется только идентификатор класса. Никакой автоматической работы с классом-родителем также не предусмотрено. Методы readObject и writeObject игнорируются. Ключевое слово transient эффекта на Externalizable не имеет.
Externalizable объект в отличие от Serializable десерализуется не в обход конструктора, так что должен иметь конструктор без аргументов.
Подробнее читайте в соответствующем вопросе на stackoverflow.
#СериализацияSerializable класс имеет цепочку родителей, пока эти родители тоже Serializable, десериализация объекта идет от родителя к наследнику, в обход конструктора. Вместо него вызываются методы readObject (readObjectNoData). Но как только встречается первый предок, не реализующий интерфейс Serializable, инициализация для него возвращается в нормальное русло – вместо readObject вызывается конструктор без аргументов. Если такого конструктора нет, или он объявлен private, исполнение выбросит InvalidClassException.
При сериализации несериализуемые предки просто игнорируются.
Если класс несериализуемый и не предоставляет достаточного доступа к своему логическому состоянию для наследников, правильно реализовать его наследника сериализуемым может быть невозможно.
Популярный вопрос на тему – как когда сериализуешь объект класса-наследника, избежать сериализации его родительской части. Единственный способ добиться этого – кастомизировать сериализационную форму, определив собственную реализацию writeObject(), либо используя интерфейс Externalizable.
Открытость класса для наследования делает неприменимым паттерн serialization proxy (который рассмотрим позднее).
#СериализацияSerializable пуст, но есть ряд методов, добавив которые в сериализуемый класс можно добиться изменения этапов процесса сериализации и десериализации.
readObjectNoData() используется для инициализации класса-родителя, который при сериализации оригинального объекта еще не был родителем. Подробное объяснение.
readObject(ObjectInputStream s) переопределяет стандартную десериализацию.
Методы readObject* похожи на конструктор. Как и конструктор, они подвержены проблеме виртуального вызова. Как и конструктор, они используются для поддержания инвариантов класса (только для случая десериализации).
writeObject(ObjectOutputStream s) используется для записи собственной сериализационной формы.
Object readResolve() может использоваться для реализации какого-либо порождающего паттерна при десериализации. Даже при его использовании объект сначала будет десериализован, поэтому рекомендуется вместе с этим методом помечать все поля transient. Видимость этого метода для наследника определяет, будет ли наследник вызывать его.
Для подмены объекта при записи добавляется симметричный метод Object writeReplace().
Интерфейс Externalizable дает инструмент полной подмены реализации сериализации. Рассмотрим его в следующих постах.
#СериализацияserialVersionUID. Это число типа long, которое представляет собой «версию» сериализационной формы класса. Если при сериализации/десериализации значения serialVersionUID не совпадают – будет выброшено InvalidClassException.
Для совпадающих версий работает мощная поддержка эволюции класса – совместимые изменения, такие как добавление или удаление полей, не приводят к InvalidClassException.
Неявное значение вычисляется автоматически в рантайме, и включает в себя информацию о имени типа, списке родителей и полей (с точностью до коллизии). По смыслу это похоже на хэш-сумму класса. Соответственно, при любом изменении класса значение изменится, и поддержка эволюции окажется бесполезной.
Всегда лучше явно указывать любое значение serialVersionUID, и изменять только в тех редких случаях, когда требуется сломать совместимость с предыдущими версиями. Стандартная утилита JDK serialver умеет «угадывать» авто-генерированное значение. Она используется чтобы зафиксировать значение для включения поддержки эволюции созданного ранее класса.
Явное значение устанавливается в переменную static final long serialVersionUID.
#СериализацияSerializable (Externalizable), и цель записи/источник чтения ObjectInputStream/ObjectOutputStream (ObjectInput/ObjectOutput).
Класс сериализуем, если:
🔘 Реализует маркерный интерфейс Serializable;
🔘 Все поля сериализуемые или помечены модификатором transient (иначе рантайм выбросит NotSerializableException).
Протокол стандартной сериализации описан в документации.
Сериализационная форма может, и в некоторых случаях для корректной работы должна быть кастомизирована. Правильная форма содержит только логическое представление данных, без деталей о физической реализации.
Для описания полей сериализационной формы в javadoc-документации используется тэг @serial. Для документации генерирующего нестандартную сериализационную форму метода используется @serialData. Эти тэги имеют смысл и для приватных членов, так как эффективно такие члены – часть публичного API.
Нестатические внутренние классы не должны быть сериализуемыми. Статические поля как поля класса а не инстанса несериализуемы.
Сериализации посвящен целый раздел Effective Java. Доклад для ознакомления с темой.
#Сериализацияchar[] value и int hash. В поле hash кэшируется хэш-сумма при первом подсчете для соблюдения контракта метода hashCode.
До Java 7 были еще поля offset и count – чтобы переиспользовать без пересоздания массивы из билдеров и других строк. В современной джаве от этого отказались в угоду меньшего потребления памяти.
Изначально все строки хранились в кодировке UTF-16, каждый символ занимал по два байта и умещался в char. Однако выяснилось, что статистически большинство строк содержит только ASCII-символы, которые вмещаются в один байт и составляют кодировку LATIN-1. То есть старший байт в большинстве char остается нулевым, и строки наполовину состоят из пустоты. А примерно четверть памяти приложений состоит из одних только строк.
В Java 6 была введена экспериментальная фича Compressed Strings – способность строки хранить строки в LATIN-1 в массиве byte вместо char. С этой фичей был ряд проблем, и позднее ее убрали.
Снова сжатие строк появилось в Java 9 – теперь оно называется Compact Strings и включено по умолчанию. В классе String появилось поле coder, которое переключает кодировки, и статический флаг COMPACT_STRINGS, выключающий фичу вообще. Тип массива value окончательно изменился с char[] на byte[].
Для полного обзора особенностей класса String стоит посмотреть доклады Алексея Шипилёва (1, 2).
#Строкиchar. Значит, корректный ответ нужно начать с уточнения: подразумевается ли обход значений char или code point.
Из этого следует, что и длина строки, верхняя граница итерации – тоже понятие неоднозначное. Метод length() на самом деле возвращает не количество Unicode-символов, а количество значений char. Реальную логическую длину (количество кодовых точек) покажет метод codePointCount(). Нужно помнить, что чтобы обнаружить суррогатные пары, внутри ему придется проитерировать по символам.
Итерироваться по char можно либо получая по одному символу с помощью метода charAt(), либо со всем массивом сразу, методом toCharArray(). В случае с массивом создается копия внутреннего значения – это естественно медленнее, зато этот массив-копию можно мутировать. Работать с суррогатными парами придется вручную, для этого в классе Character есть специальные методы.
Другой вариант – сразу оперировать методами codePointAt() и codePointBefore(). Параметром указываются индексы массива char, но результатом будут кодовые точки типа int.
В Java 8 появился новый удобный способ обхода – методы chars() и codePoints(). Они возвращают IntStream из символов и кодовых точек соответственно. Носителем результирующих стримов выступает оригинальное внутреннее значение строки, копирование массива не требуется.
#Строки
Endi mavjud! Telegram Tadqiqoti 2025 — yilning asosiy insaytlari 
