Телеграм

Android under the hood

@android_under_the_hood Программирование и разработка
РКН: проверяем Иноагент: проверяем
Разбираю Android, Kotlin и JVM изнутри.
Коллекции • Coroutines • Compose • JVM • Android internals

while (isAlive) { beHappy(); }

лс: @dmitry_tsyvtsyn
сайт: androidunderthehood.ru

Статистика обновлена 13.11.2026 в 18:33 · 1 просмотр страницы · Хотите больше просмотров?

Подписчики1 518
Охват поста1 017 67% от подписчиков
ERR за месяц67,00%
ERR за 24 часа32,61%

Динамика за 30 дней

Рекламные публикации

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

Последние публикации

Все посты канала →
Android under the hood tg1.5 тыс. подписчиков
Открыть пост ↗
Dev Easy Notes.

Давно хотел поделиться каналом, с которого начался мой канал, ведь именно им я вдохновлялся когда принимал решение о создании своего собственного:

https://t.me/dev_easy_notes

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

Ну и не менее важное, стилистика картинок моего канала была основана на некоторых иллюстрациях взятых из
@dev_easy_notes, так что на него однозначно стоит подписаться)
👁 495 ❤ 3 ↻ 1 11 ноября
Android under the hood tg1.5 тыс. подписчиков
Открыть пост ↗
java.lang.AbstractStringBuilder.

Вся базовая логика по изменению строк в StringBuilder / StringBuffer лежит в одном базовом классе:

abstract class AbstractStringBuilder implements ... {
// изменяемый массив байтов
byte[] value;

// если символы хранятся одним байтом (LATIN1) то coder равен нулю, если двумя (UTF16) coder равен 1
byte coder;

// количество символов, а не байтов: один символ может хранится двумя байтами (кириллица в UTF16)
int count;

...
}


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

public AbstractStringBuilder append(String str) {
if (str == null) {
return appendNull();
}
int len = str.length();
// если в массиве не хватает места для новой строки создается новый
ensureCapacityInternal(count + len);
putStringAt(count, str);
// count это количество символов, не байт!
count += len;
return this;
}

private void ensureCapacityInternal(
int minimumCapacity
) {
// так определяется количество символов в массиве, если на символ приходится 1 байт, то coder == 0, длина вернется как есть, а если на символ приходится 2 байта, то coder == 1, тогда произойдет сдвиг вправо на единицу, а это деление на 2
int oldCapacity = value.length >> coder;
// если для новых символов нет места создаем новый массив
if (minimumCapacity - oldCapacity > 0) {
// создает копию массива с большим размером
value = Arrays.copyOf(
value,
// newCapacity() вернет новый размер массива в символах, а нам нужно в байтах, поэтому добавляется coder, при coder == 0 ничего не произойдет, так как каждый символ это один байт, а при coder == 1 произойдет сдвиг влево на 1, а это умножение на 2
newCapacity(minimumCapacity) << coder
);
}
}


Метод newCapacity() либо возвращает минимально необходимый размер либо размер в 2 раза больший текущего размера, в ArrayList кстати используется коэффициент в 1.5 раза.

Добавление строки через append() метод это самая обычная вставка байтов строки в массив байтов AbstractStringBuilder:

// чуток упростил метод
private void putStringAt(
// index == count, то есть вставка в конец
int index,
String str
) {
// если строка пришла в UTF16 надо расширить текущий массив до 2 байтов на 1 символ
if (getCoder() != str.coder()) {
inflate();
}
// байты строки копируются в текущий массив байтов
str.getBytes(
value, 0,
index, coder, str.length()
);
}


Для строк не такая интересная логика как для чисел, но обо этом в другой раз.

P.S. Урок по LinkedList уже на подходе https://androidunderthehood.ru/courses/kotlin-jvm-data-structures
👁 842 ❤ 6 ↻ 6 5 ноября
Android under the hood tg1.5 тыс. подписчиков
Открыть пост ↗
StringBuilder vs StringBuffer.

Посмотрим и сравним исходники обеих классов:

// вся работа с изменяемым массивом байтов спрятана в AbstractStringBuilder
public final class StringBuilder extends AbstractStringBuilder implements ...
{

// тута нет synchronized
public StringBuilder append(char[] str) {
super.append(str);
return this;
}
}

// также расширяет AbstractStringBuilder и все те же интерфейсы, опустил для простоты
public final class StringBuffer extends AbstractStringBuilder implements ...
{

// тут есть synchronized
public synchronized StringBuffer append(
char[] str
) {
// вызов toString() кэшируется для оптимизации
toStringCache = null;
super.append(str);
return this;
}
}


В примере приведен один вариант метода append(), все остальные сделаны по аналогии, единственное отличие между StringBuilder и StringBuffer в том что второй использует ключевое слово synchronized, которое позволяет менять массив байтов только одному потоку за раз.

Помимо методов для изменения массива байтов в StringBuffer также синхронизированы:

// возвращает количество добавленных байтов: символов, чисел, строк и тд
public synchronized int length() {
return count;
}

// возвращает размер массива байтов, не всегда равный фактическому количеству байтов
public synchronized int capacity() {
return super.capacity();
}

// В ArrayList есть похожий метод, который увеличивает размер массива, тут аналогично, только массив байтов
public synchronized void ensureCapacity(
int minimumCapacity
) {
super.ensureCapacity(minimumCapacity);
}

// когда методы меняющие массив байтов синхронизированы, появляется возможность сделать консистентный кэш
public synchronized String toString() {
if (toStringCache == null) {
toStringCache = ...
}
return new String(toStringCache);
}


По сути вся логика динамического массива байтов лежит в AbstractStringBuilder, а StringBuilder / StringBuffer всего лишь обеспечивают публичное API: один без синхронизации между потоками, другой с синхронизацией.

P.S. Выложил наконец-то второй урок по ArrayList, больше тысячи строк текста, наслаждайтесь:
https://androidunderthehood.ru/courses/kotlin-jvm-data-structures
👁 1.1 тыс. ❤ 5 💬 2 ↻ 7 29 октября