Ответ
Лямбда в Kotlin/Java — это синтаксический сахар для функциональных интерфейсов (SAM). Под капотом:
- Для Java: создается анонимный класс, реализующий интерфейс с одним методом (например,
Runnable,OnClickListener).
button.setOnClickListener(v -> { /* code */ });
// Превращается в:
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) { /* code */ }
});
- Для Kotlin: если лямбда не захватывает переменные, генерируется синглтон-объект для оптимизации. При захвате — создается новый объект при каждом вызове.
Особенности:
- Нет оверхеда в рантайме (если не захватывает контекст)
- В Kotlin может быть inline (оптимизация байт-кода)
- Не является точным аналогом Java 8 лямбд (там используется
invokedynamic)
Ответ 18+ 🔞
А, лямбды! Ну, это ж классика, ебушки-воробушки. Смотри, чтобы не охуеть от умных слов, давай на пальцах.
Представь, что тебе надо передать кусок кода как аргумент. Раньше в Яве это была такая пиздопроебибна с анонимными классами — строчек двадцать, где по делу одна. А теперь ты просто пишешь стрелочку -> и всё. Красота!
Под капотом-то что? Ну, там магия, но не особо сложная.
-
В Яве компилятор видит твою короткую запись и думает: «Ага, чувак, ты хочешь передать действие. Ща я тебе разверну это в полноценный анонимный класс, как в старые добрые». То есть твой красивый код:
button.setOnClickListener(v -> { /* code */ });...превращается во что-то монструозное, но знакомое:
button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { /* code */ } });По сути, синтаксический сахар, да такой сладкий, что диабет заработать можно.
-
В Котлине ребята пошли дальше. Они такие: «Зачем каждый раз новый объект создавать, если лямбда ничего извне не трогает?». И если твоя лямбда не захватывает переменные из внешней области видимости, то под капотом создаётся один синглтон-объект на всю программу и переиспользуется. Умно, да? А вот если она начинает тащить в себя внешние переменные (это называется «захват контекста»), тогда да, каждый раз будет новый объект. Волнение ебать, но логично.
На что обратить внимание, чтобы не обжечься:
- Оверхеда в рантайме практически нет, особенно если лямбда «чистая» (ничего не захватывает). Так что не бзди.
- В Котлине есть супер-фича —
inline-функции. Если функцию пометить этим словом, то компилятор не будет генерировать объект для лямбды вообще, а буквально вставит твой код на место вызова. Это овердохуища как эффективно с точки зрения байт-кода. - И главное, не путай лямбды Kotlin и Java 8. В Яве восьмой версии для этого используют инструкцию
invokedynamic— это уже другая, более низкоуровневая магия виртуальной машины. А в Котлине подход попроще, через объекты. Так что под капотом это разные вещи, хоть снаружи и выглядят похоже.
Короче, инструмент мощный и удобный. Главное — понимать, когда он создаёт объекты, а когда нет, чтобы не получить неожиданностей с производительностью. Но в 99% случаев — да похуй, пиши и радуйся.