Задумывались ли вы когда-нибудь над тем, как работает распределение памяти в Kotlin? Предлагаю погрузиться в волшебный мир стековой и кучной памяти, используя забавные аналогии из повседневной жизни. Приготовьтесь к увлекательному путешествию!
Что такое стековая память?
Представьте, что находитесь в магазине сэндвичей. Заказываете сэндвич, и повар готовит его прямо на ваших глазах. Сэндвич делается быстро, подается немедленно, и вы сразу же его съедаете. Повар не хранит запасы сэндвичей — все готовится по заказу.
В Kotlin стековая память похожа на магазин сэндвичей. Она используется для:
- локальных переменных: подобно свежеприготовленным сэндвичам, они создаются при вызове функции и исчезают при ее завершении;
- вызовов функций: каждый вызов функции подобен новому заказу в магазине сэндвичей; шеф-повар (программа) обрабатывает каждый заказ (вызов функции) по очереди, в определенной последовательности.
Рассмотрим небольшой пример:
fun makeSandwich(type: String): String {
val sandwich = "Here's your $type sandwich!" // Локальная переменная, выделяется на стеке
return sandwich
}
fun main() {
val myLunch = makeSandwich("turkey") // Вызов функции, выделяется на стеке
println(myLunch)
}
Здесь sandwich
и myLunch
похожи на сэндвичи, приготовленные на заказ. Они существуют только в области видимости соответствующих функций и очищаются, как только функции завершают свою работу.
Что такое кучная память?
Представьте большой склад для хранения товаров в течение длительного времени. Вы можете поместить туда предметы, достать их позже, и они останутся на месте, пока вы не решите их убрать. Этот огромный склад способен вместить множество товаров, но их поиск может занять определенное время, и вам придется следить за тем, где что лежит.
В Kotlin кучная память похожа на этот склад. Она используется для:
- объектов: подобные товарам, хранящимся на складе, они остаются в памяти до тех пор, пока не будут явно удалены или пока не придет сборщик мусора (волшебная команда уборщиков);
- глобальных переменных, похожих на товары, доступные из любого места склада (всего приложения).
Вот пример:
class Sandwich(val type: String, val ingredients: List<String>)
fun main() {
val mySandwich = Sandwich("turkey", listOf("turkey", "lettuce", "tomato")) // Объект, выделяется на куче
println("I made a ${mySandwich.type} sandwich with ${mySandwich.ingredients}.")
}
В данном случае mySandwich
— это объект, хранящийся в куче. Он останется там до тех пор, пока нужен вам, и будет доступен из разных частей программы.
Разложим все по полочкам: различие памяти стека и кучи
Чтобы все стало еще понятнее, прибегнем к пошаговому объяснению.
1. Вызовы функций и локальные переменные (стек):
- При вызове функции создается новый «порядок».
- Локальные переменные внутри функции подобны ингредиентам, используемым для конкретного заказа.
- После завершения работы функции заказ выполняется, а ингредиенты (локальные переменные) очищаются.
2. Объекты и глобальные переменные (куча):
- Созданный объект напоминает хранящийся на складе товар.
- Объект остается на складе до тех пор, пока не будет удален вами или пока волшебная команда уборщиков (сборщик мусора) не удалит его за вас.
- Доступ к объектам возможен из любой точки программы точно так же, как можно получить из любого места склада хранящиеся товары.
Почему это важно?
Понимание разницы между стековой и кучной памятью помогает писать более эффективный и результативный код на Kotlin. В конечном счете это позволяет лучше управлять ресурсами, избегать утечек памяти и оптимизировать производительность.
Примеры кода: собираем все вместе
Закрепим полученные знания с помощью примеров кода.
Пример стековой памяти
fun prepareOrder(order: String): String {
val preparedOrder = "Order: $order is ready!" // Локальная переменная, стек
return preparedOrder
}
fun main() {
val myOrder = prepareOrder("turkey sandwich") // Вызов функции, стек
println(myOrder)
}
Пример кучной памяти
class WarehouseItem(val name: String, val quantity: Int)
fun main() {
val item = WarehouseItem("Laptop", 50) // Объект, куча
println("Stored ${item.quantity} ${item.name}s in the warehouse.")
}
Заключение
Стековая память подобна магазину сэндвичей, быстро обрабатывающему заказы (вызовы функций) и ингредиенты (локальные переменные). Кучная память похожа на просторный склад, где объекты и глобальные переменные хранятся столько, сколько вам нужно.
Когда будете писать код на Kotlin, вспомните эти забавные аналогии и извлеките максимум пользы из управления памятью.
Читайте также:
- Ознакомление с функциями высшего порядка в Kotlin
- Принцип DRY в Kotlin: повышение качества и удобства сопровождения кода
- Освоение функциональных возможностей Kotlin
Читайте нас в Telegram, VK и Дзен
Перевод статьи Sandeep Kella: Stack vs. Heap in Kotlin: Understanding Memory