Lambda ifodalar qanday ishlaydi va 'kapot ostida' nima bo'ladi?
sobes.tech AI
AIdan javob
Java'dagi lambda ifodalar quyidagi mexanizmlar orqali ishlaydi:
-
Funktsional interfeyslar: Lambda ifodasi o'zgaruvchiga tayinlanishi, metoddan qaytarilishi yoki metodga o'tkazilishi kerak, uning turi funktsional interfeys bo'lishi kerak. Funktsional interfeys faqat bitta abstrakt metodga (SAM - Single Abstract Method) ega bo'lgan interfeysdir.
@FunctionalInterfaceannotatsiyasi ixtiyoriy, lekin kompilyator tomonidan tekshirish uchun tavsiya etiladi. -
InvokeDynamic (invokeDynamic): Java avvalgi versiyalarda bo'lgani kabi anonim ichki sinf yaratish o'rniga,
invokeDynamicbuyrug'idan foydalanadi. Bu buyruq Java 7 da JVM'da dinamik turdagi tillarni qo'llab-quvvatlash uchun qo'shilgan va Java 8 da lambda ifodalarini va metodga havolalarni amalga oshirish uchun ishlatiladi.invokeDynamicmetod chaqiruvining hal qilinishini ish vaqtiga qoldiradi.
Nima bo'layapti 'orqa fon':
Kompilyatsiya bosqichida:
- Kompilyator lambda ifodasini tahlil qiladi.
- Lambda'ga murojaat qilayotgan funktsional interfeys turini aniqlaydi.
- O'sha sinfda (odatda
lambda$prefiksi bilan) lambda mantiqini o'z ichiga olgan maxsus sintetik metod yaratadi. Bu metod funktsional interfeysning abstrakt metodiga mos keladigan imzoga ega. - Lambda ishlatiladigan joyda, kompilyator
invokeDynamicbuyrug'ini generatsiya qiladi. Bu buyruq bootstrap method (LambdaMetafactory.metafactory) ga havolani o'z ichiga oladi.
Ishga tushirish bosqichida:
- JVM
invokeDynamicbuyrug'ini ko'rganida, birinchi marta bootstrap method (LambdaMetafactory.metafactory) ni chaqiradi. - Bootstrap method xotirada dinamik tarzda call site ni yaratadi.
- Call site funktsional interfeysni amalga oshiradigan sinfni yaratadi va qaytaradi. Bu sinf:
- To'g'ridan-to'g'ri (masalan,
Constant CallSiteyordamida) yaratilgan bo'lishi mumkin. - Keyingi foydalanish uchun keshlangan bo'lishi mumkin.
- Allaqachon mavjud bo'lgan funktsional interfeys nusxasiga havola sifatida ko'rsatilishi mumkin.
- To'g'ridan-to'g'ri (masalan,
- Bu yaratilgan sinf, funktsional interfeysning abstrakt metod chaqiruvini, kompilyator tomonidan yaratilgan sintetik metod (
lambda$) ga yo'naltiradi. - Birinchi bootstrap method chaqirilgandan so'ng, call site qaysi ob'ektni qaytarishni eslab qoladi, va keyingi
invokeDynamicchaqiruvlari, ayni lambda uchun, bu ob'ektni tezda olishi yoki to'g'ridan-to'g'ri chaqirishi mumkin, bootstrap method ni takror chaqirmasdan.
Shunday qilib, lambdalar har bir instansiya uchun yangi sinf yaratmaydi. Dış muhitdan o'zgaruvchilarni yakalagan (stateless) lambdalar uchun, funktsional interfeysning amalga oshirilishi singleton yoki keshga olingan va qayta ishlatiladigan instansiya bo'lishi mumkin. O'zgaruvchilarni yakalagan (stateful) lambdalar esa, yakalanadigan o'zgaruvchilarni saqlovchi yangi sinf instansiyasini yaratishni talab qiladi.
invokeDynamic dan foydalanish, JIT-kompilyatorga, funktsional interfeys metod chaqiruvlarini an'anaviy anonim sinflardan ko'ra samaraliroq optimallashtirish imkonini beradi, chunki JIT ish vaqtida ko'proq ma'lumotli qarorlar qabul qilishi mumkin.
// Funktsional interfeys misoli
@FunctionalInterface
interface MyFunction {
String apply(String input);
}
public class LambdaExample {
public static void main(String[] args) {
// Lambda ifodasidan foydalanish
MyFunction func = s -> "Processed: " + s;
String result = func.apply("Test");
System.out.println(result);
}
}