Sobes.tech
Middle+

Чӣ тавр ифодаҳои ламбда кор мекунанд ва чӣ рӯй медиҳад 'зери капот'?

sobes.tech AI

Ҷавоб аз AI

Экспрешнҳои lambda дар Java тавассути механизмҳои зерин кор мекунанд:

  1. Интерфейсҳои функсионалӣ: Экспрешнҳои lambda бояд ба тағйирёбанда таъин карда шаванд, аз метод баргардонида шаванд ё ба методе гузошта шаванд, ки навъи он интерфейси функсионалӣ мебошад. Интерфейси функсионалӣ — ин интерфейс бо дақиқ як методи абстрактӣ (SAM - Single Abstract Method). Анотацияи @FunctionalInterface ихтиёрӣ аст, аммо тавсия дода мешавад барои санҷиши компилятор.

  2. Динамикӣ (invokeDynamic): Ба ҷои он ки дар байткод дар вақти компиляция синфи анонимӣ эҷод кунад, Java истифодаи дастурро invokeDynamic мекунад. Ин дастур дар Java 7 барои дастгирии забонҳои динамикӣ дар JVM илова шуд ва дар Java 8 барои иҷрои экспрешнҳои lambda ва истинодҳо ба методҳо истифода мешавад. invokeDynamic дар ҳоле ки дақиқ кардани даъвати методро ба вақти иҷро (runtime) мепечад.

Он чӣ дар "под капот" рӯй медиҳад:

Дар марҳилаи компиляция:

  • Компилятор экспрешнҳои lambda-ро таҳлил мекунад.
  • Навъи интерфейси функсионалӣ, ки ба он lambda ишора мекунад, муайян мекунад.
  • Методи синтетикии махсус (одатан бо префикси lambda$) дар ҳамон синф эҷод мешавад, ки логикаи экспрешнҳои lambda-ро дорад. Ин метод ҳамон сигнатураи методи абстрактии интерфейси функсионалӣ дорад.
  • Дар ҷойи истифодаи lambda, компилятор дастурро invokeDynamic эҷод мекунад. Ин дастур ба bootstrap method (LambdaMetafactory.metafactory) ишора мекунад.

Дар марҳилаи иҷро:

  • Вақте ки JVM ба дастур invokeDynamic меояд, аввалин бор bootstrap method (LambdaMetafactory.metafactory) даъват мешавад.
  • Bootstrap method (LambdaMetafactory.metafactory) динамикӣ дар ёддошт call site эҷод мекунад.
  • Call site як экземпляри синфро, ки интерфейси функсионалиро иҷро мекунад, эҷод ва бармегардонад. Ин экземпляр метавонад:
    • Дар ҷойи худ (масалан, бо кӯмак аз Constant CallSite) эҷод шавад.
    • Барои истифодаи баъдӣ кеш шавад (барои lambda бе ҳолат).
    • Ба як экземпляри аллакай мавҷудбудаи интерфейси функсионалӣ ишора кунад (масалан, барои lambda бе ҳолат, ки Serializable-ро иҷро мекунад).
  • Ин синфи эҷодшуда, даъвати методи абстрактии интерфейси функсионалӣ-ро ба методи синтетикии эҷодшуда (lambda$) делегат мекунад.
  • Пас аз даъвати аввал, bootstrap method объектро, ки бояд баргардонида шавад, меморизатсия мекунад ва даъватҳои минбаъдаи invokeDynamic барои ҳамон lambda метавонанд ба зудӣ ин объектро дастрас кунанд ё мустақиман ба он занг зананд, бе даъвати дубора ба bootstrap method.

Ҳамин тариқ, lambda-ҳо ҳамеша синф нав эҷод намекунанд барои ҳар як намунасозӣ. Барои lambda-ҳое, ки тағйирёбандаҳоро аз муҳити беруна (stateless lambda) намегирад, иҷрои интерфейси функсионалӣ метавонад singleton ё намунаи кешшуда бошад, ки дубора истифода мешавад. Lambda-ҳое, ки тағйирёбандаҳоро (stateful lambda) мегиранд, талаб мекунанд, ки намунаи нав эҷод шавад, ки тағйирёбандаҳоро нигоҳ медорад.

Истифодаи invokeDynamic имкон медиҳад, ки JIT-компилятор иҷрои даъватҳои методи интерфейси функсионалӣ самараноктар оптимизатсия кунад, нисбат ба моделҳои анъанавии синфҳои анонимӣ, зеро JIT метавонад қарорҳои бештар маълумро дар вақти иҷро қабул кунад.

// Мисоли интерфейси функсионалӣ
@FunctionalInterface
interface MyFunction {
    String apply(String input);
}

public class LambdaExample {
    public static void main(String[] args) {
        // Истифодаи экспрешнҳои lambda
        MyFunction func = s -> "Processed: " + s;

        String result = func.apply("Test");
        System.out.println(result);
    }
}