JavaRush /Blog Jawa /Random-JV /Populer babagan ekspresi lambda ing basa Jawa. Kanthi con...

Populer babagan ekspresi lambda ing basa Jawa. Kanthi conto lan tugas. Bagean 2

Diterbitake ing grup
Artikel iki kanggo sapa?
  • Kanggo sing maca bagean pisanan saka artikel iki;

  • Kanggo sing mikir wis ngerti Java Core, nanging ora ngerti babagan ekspresi lambda ing basa Jawa. Utawa, mbok menawa, sampeyan wis krungu bab lambdas, nanging tanpa rincian.

  • kanggo sing duwe sawetara pangerten saka lambda expression, nanging isih wedi lan mboten umum kanggo nggunakake.

Akses menyang variabel eksternal

Bakal kode iki ngumpulake karo kelas anonim?
int counter = 0;
Runnable r = new Runnable() {
    @Override
    public void run() {
        counter++;
    }
};
Ora. Variabel counterkudu final. Utawa ora mesthi final, nanging ing kasus apa wae ora bisa ngganti regane. Prinsip sing padha digunakake ing ekspresi lambda. Dheweke duwe akses menyang kabeh variabel sing "katon" saka panggonan sing diumumake. Nanging lambda ora kudu ngganti (nemtokake nilai anyar). Bener, ana pilihan kanggo ngliwati watesan iki ing kelas anonim. Cukup mung nggawe variabel saka jinis referensi lan ngganti kahanan internal obyek kasebut. Ing kasus iki, variabel dhewe bakal nuding obyek sing padha, lan ing kasus iki sampeyan bisa kanthi aman nunjukake minangka final.
final AtomicInteger counter = new AtomicInteger(0);
Runnable r = new Runnable() {
    @Override
    public void run() {
        counter.incrementAndGet();
    }
};
Ing kene variabel kita counterminangka referensi kanggo jinis obyek AtomicInteger. Lan kanggo ngganti kahanan obyek iki, cara digunakake incrementAndGet(). Nilai variabel kasebut dhewe ora owah nalika program lagi mlaku lan tansah nuding obyek sing padha, sing ngidini kita langsung ngumumake variabel kanthi tembung kunci final. Conto sing padha, nanging nganggo ekspresi lambda:
int counter = 0;
Runnable r = () -> counter++;
Ora kompilasi kanthi alesan sing padha karo pilihan karo kelas anonim: counterora kudu diganti nalika program lagi mlaku. Nanging kaya iki - kabeh apik:
final AtomicInteger counter = new AtomicInteger(0);
Runnable r = () -> counter.incrementAndGet();
Iki uga ditrapake kanggo cara nelpon. Saka njero ekspresi lambda, sampeyan ora mung bisa ngakses kabeh variabel "katon", nanging uga nelpon cara sing bisa diakses.
public class Main {
    public static void main(String[] args) {
        Runnable runnable = () -> staticMethod();
        new Thread(runnable).start();
    }

    private static void staticMethod() {
        System.out.println("Я - метод staticMethod(), и меня только-что кто-то вызвал!");
    }
}
Senajan cara staticMethod()iku pribadi, iku "diakses" kanggo disebut nang cara main(), supaya iku uga bisa diakses kanggo nelpon saka njero lambda sing digawe ing cara main.

Wayahe eksekusi kode ekspresi lambda

Pitakonan iki bisa uga katon gampang banget kanggo sampeyan, nanging sampeyan kudu takon: kapan kode ing ekspresi lambda bakal dieksekusi? Ing wayahe nggawe? Utawa ing wayahe nalika (isih ora dingerteni ing ngendi) bakal diarani? Iku cukup gampang kanggo mriksa.
System.out.println("Запуск программы");

// много всякого разного codeа
// ...

System.out.println("Перед объявлением лямбды");

Runnable runnable = () -> System.out.println("Я - лямбда!");

System.out.println("После объявления лямбды");

// много всякого другого codeа
// ...

System.out.println("Перед передачей лямбды в тред");
new Thread(runnable).start();
Output sing ditampilake:
Запуск программы
Перед объявлением лямбды
После объявления лямбды
Перед передачей лямбды в тред
Я - лямбда!
Bisa dideleng manawa kode ekspresi lambda dieksekusi ing pungkasan, sawise benang digawe lan mung nalika proses eksekusi program tekan eksekusi metode kasebut run(). Lan ora ing wektu woro-woro. Kanthi ngumumake ekspresi lambda, kita mung nggawe obyek saka jinis kasebut Runnablelan nggambarake prilaku metode kasebut run(). Cara kasebut dhewe diluncurake mengko.

Referensi metode?

Ora ana hubungane langsung karo lambdas dhewe, nanging aku mikir bakal logis kanggo ngomong sawetara tembung babagan iki ing artikel iki. Ayo dadi ngomong kita duwe expression lambda sing ora nindakake apa-apa khusus, nanging mung nelpon sawetara cara.
x -> System.out.println(x)
Wong-wong mau diwènèhi apa-apa х, banjur diceluk System.out.println()lan dilewati ing kana х. Ing kasus iki, kita bisa ngganti karo link kanggo cara kita kudu. Kaya iki:
System.out::println
Ya, tanpa tanda kurung ing pungkasan! Tuladha luwih lengkap:
List<String> strings = new LinkedList<>();
strings.add("Mother");
strings.add("soap");
strings.add("frame");

strings.forEach(x -> System.out.println(x));
Ing baris pungkasan kita nggunakake cara forEach()sing nampa obyek antarmuka Consumer. Iki maneh antarmuka fungsional karo mung siji cara void accept(T t). Patut, kita nulis ekspresi lambda sing njupuk siji parameter (amarga diketik ing antarmuka dhewe, kita ora nuduhake jinis parameter kasebut, nanging nuduhake yen bakal diarani х). Ing awak ekspresi lambda kita nulis kode kasebut. sing bakal dieksekusi nalika metode kasebut diarani accept(). Ing kene kita mung nampilake ing layar apa sing ana ing variabel х. Cara kasebut dhewe forEach()ngliwati kabeh unsur koleksi, nelpon Consumermetode obyek antarmuka sing diterusake (lambda kita) accept(), ing ngendi iku ngliwati saben unsur saka koleksi. Kaya sing wis dakkandhakake, iki minangka lambda -ekspresi (mung nelpon cara liya) kita bisa ngganti kanthi referensi kanggo metode sing kita butuhake. Banjur kode kita bakal katon kaya iki:
List<String> strings = new LinkedList<>();
strings.add("Mother");
strings.add("soap");
strings.add("frame");

strings.forEach(System.out::println);
Ingkang utama yaiku paramèter sing ditampa saka metode (println()lan accept()). Amarga cara kasebut println()bisa nampa apa wae (kakehan kanggo kabeh primitif lan kanggo obyek apa wae), tinimbang ekspresi lambda, kita bisa ngliwati forEach()mung referensi kanggo metode kasebut println(). Banjur forEach()bakal njupuk saben unsur koleksi lan langsung menyang cara println().Kanggo wong-wong sing nemokke iki kanggo pisanan, elinga Wigati dimangerteni menawa kita ora nelpon cara System.out.println()(kanthi titik ing antarane tembung lan karo kurung ing mburi), nanging kita pass referensi kanggo cara iki dhewe.
strings.forEach(System.out.println());
kita bakal duwe kesalahan kompilasi. Amarga sadurunge nelpon forEach(), Jawa bakal weruh yen lagi disebut System.out.println(), bakal ngerti yen lagi bali voidlan bakal nyoba voidkanggo pass iki kanggo forEach()obyek saka jinis sing nunggu ana Consumer.

Sintaks kanggo nggunakake Referensi Metode

Iku cukup prasaja:
  1. Maringaken referensi kanggo cara statisNameКласса:: NameСтатическогоМетода?

    public class Main {
        public static void main(String[] args) {
            List<String> strings = new LinkedList<>();
            strings.add("Mother");
            strings.add("soap");
            strings.add("frame");
    
            strings.forEach(Main::staticMethod);
        }
    
        private static void staticMethod(String s) {
            // do something
        }
    }
  2. Maringaken referensi kanggo cara non-statis nggunakake obyek anaNameПеременнойСОбъектом:: method name

    public class Main {
        public static void main(String[] args) {
            List<String> strings = new LinkedList<>();
            strings.add("Mother");
            strings.add("soap");
            strings.add("frame");
    
            Main instance = new Main();
            strings.forEach(instance::nonStaticMethod);
        }
    
        private void nonStaticMethod(String s) {
            // do something
        }
    }
  3. We pass referensi kanggo cara non-statis nggunakake kelas kang cara iki dileksanakakeNameКласса:: method name

    public class Main {
        public static void main(String[] args) {
            List<User> users = new LinkedList<>();
            users.add(new User("Vasya"));
            users.add(new User("Коля"));
            users.add(new User("Петя"));
    
            users.forEach(User::print);
        }
    
        private static class User {
            private String name;
    
            private User(String name) {
                this.name = name;
            }
    
            private void print() {
                System.out.println(name);
            }
        }
    }
  4. Maringaken link menyang konstruktor NameКласса::new
    Nggunakake pranala cara trep banget nalika ana cara siap-digawe sing rampung wareg karo, lan sampeyan pengin nggunakake minangka callback. Ing kasus iki, tinimbang nulis ekspresi lambda nganggo kode metode kasebut, utawa ekspresi lambda sing diarani metode iki, kita mung menehi referensi. Mekaten.

Bedane menarik antarane kelas anonim lan ekspresi lambda

Ing kelas anonim, tembung kunci thisnuduhake obyek saka kelas anonim kasebut. Lan yen kita nggunakake thisnang lambda, kita bakal entuk akses menyang obyek saka kelas rongko. Where kita bener wrote expression iki. Iki kedadeyan amarga ekspresi lambda, nalika dikompilasi, dadi metode pribadi ing kelas sing ditulis. Aku ora nyaranake nggunakake "fitur" iki, amarga duwe efek samping, sing mbantah prinsip pemrograman fungsional. Nanging pendekatan iki cukup konsisten karo OOP. ;)

Saka ngendi aku entuk informasi utawa apa sing kudu diwaca

Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION