Чӣ тавр ифодаҳои ламбда кор мекунанд ва чӣ рӯй медиҳад 'зери капот'?
sobes.tech AI
Ҷавоб аз AI
Экспрешнҳои lambda дар Java тавассути механизмҳои зерин кор мекунанд:
-
Интерфейсҳои функсионалӣ: Экспрешнҳои lambda бояд ба тағйирёбанда таъин карда шаванд, аз метод баргардонида шаванд ё ба методе гузошта шаванд, ки навъи он интерфейси функсионалӣ мебошад. Интерфейси функсионалӣ — ин интерфейс бо дақиқ як методи абстрактӣ (SAM - Single Abstract Method). Анотацияи
@FunctionalInterfaceихтиёрӣ аст, аммо тавсия дода мешавад барои санҷиши компилятор. -
Динамикӣ (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);
}
}