CodeGym /Blog Jawa /Acak /Panjelasan babagan ekspresi lambda ing basa Jawa. Kanthi ...
John Squirrels
tingkat
San Francisco

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

Diterbitake ing grup
Artikel iki kanggo sapa?
  • Iku kanggo wong sing maca bagean pisanan saka artikel iki;
  • Iku kanggo wong sing mikir wis ngerti Java Core, nanging ora ngerti babagan ekspresi lambda ing basa Jawa. Utawa mungkin dheweke wis krungu babagan ekspresi lambda, nanging rincian kurang.
  • Iku kanggo wong sing duwe pangerten tartamtu babagan ekspresi lambda, nanging isih wedi karo dheweke lan ora biasa nggunakake.
Yen sampeyan ora cocog karo salah siji saka kategori iki, sampeyan bisa nemokake artikel iki mboseni, cacat, utawa umume ora cangkir teh. Ing kasus iki, aja ragu-ragu pindhah menyang perkara liyane utawa, yen sampeyan wis ngerti babagan topik kasebut, mangga menehi saran ing komentar babagan carane aku bisa nambah utawa nambah artikel kasebut. Panjelasan babagan ekspresi lambda ing basa Jawa.  Kanthi conto lan tugas.  Bagean 2 - 1Materi kasebut ora ngaku nduweni nilai akademis, apamaneh kebaruan. Kosok baline: Aku bakal nyoba njlèntrèhaké bab-bab sing rumit (kanggo sawetara wong) kanthi gampang. A panjalukan kanggo nerangake Stream API inspirasi kula kanggo nulis iki. Aku mikir babagan iki lan mutusake manawa sawetara conto streamku ora bisa dingerteni tanpa ngerti ekspresi lambda. Dadi, kita bakal miwiti nganggo ekspresi lambda.

Akses menyang variabel eksternal

Apa kode iki kompilasi karo kelas anonim?

int counter = 0;
Runnable r = new Runnable() { 

    @Override 
    public void run() { 
        counter++;
    }
};
Ora. counter Variabel kudu final. Utawa yen ora final, banjur paling ora bisa ngganti regane. Prinsip sing padha ditrapake ing ekspresi lambda. Dheweke bisa ngakses kabeh variabel sing bisa "dideleng" saka papan sing diumumake. Nanging lambda ora kudu ngganti (nemtokake nilai anyar kanggo dheweke). Nanging, ana cara kanggo ngliwati watesan iki ing kelas anonim. Mung nggawe variabel referensi lan ngganti negara internal obyek. Kanthi mengkono, variabel kasebut dhewe ora owah (nuduhake obyek sing padha) lan bisa ditandhani kanthi aman 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 AtomicIntegerobyek. Lan incrementAndGet()cara digunakake kanggo ngganti kahanan obyek iki. Nilai variabel dhewe ora owah nalika program lagi mlaku. Iku tansah nuduhake obyek sing padha, sing ngidini kita ngumumake variabel kasebut kanthi tembung kunci pungkasan. Ing ngisor iki conto sing padha, nanging nganggo ekspresi lambda:

int counter = 0;
Runnable r = () -> counter++;
Iki ora bakal dikompilasi kanthi alasan sing padha karo versi kanthi kelas anonim:  counterora kudu diganti nalika program lagi mlaku. Nanging kabeh apik yen kita nindakake kaya iki:

final AtomicInteger counter = new AtomicInteger(0); 
Runnable r = () -> counter.incrementAndGet();
Iki uga ditrapake kanggo cara nelpon. Ing 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("I'm staticMethod(), and someone just called me!");
    }
}
Sanajan staticMethod()pribadi, bisa diakses ing main()metode kasebut, saengga bisa uga diarani saka njero lambda sing digawe ing mainmetode kasebut.

Nalika ekspresi lambda dieksekusi?

Sampeyan bisa uga nemokake pitakonan ing ngisor iki gampang banget, nanging sampeyan kudu takon mung padha: kapan kode ing ekspresi lambda bakal dieksekusi? Nalika iku digawe? Utawa nalika diarani (sing durung dingerteni)? Iki cukup gampang kanggo mriksa.

System.out.println("Program start"); 

// All sorts of code here
// ...

System.out.println("Before lambda declaration");

Runnable runnable = () -> System.out.println("I'm a lambda!");

System.out.println("After lambda declaration"); 

// All sorts of other code here
// ...

System.out.println("Before passing the lambda to the thread");
new Thread(runnable).start(); 
Output layar:

Program start
Before lambda declaration
After lambda declaration
Before passing the lambda to the thread
I'm a lambda!
Sampeyan bisa ndeleng manawa ekspresi lambda dieksekusi ing pungkasan, sawise thread digawe lan mung nalika eksekusi program tekan run()metode kasebut. Mesthi ora nalika diumumake. Kanthi ngumumake ekspresi lambda, kita mung nggawe Runnableobyek lan nggambarake cara run()tumindake. Cara kasebut dhewe ditindakake mengko.

Referensi metode?

Referensi metode ora langsung ana hubungane karo lambdas, nanging aku rumangsa bisa ngomong sawetara tembung babagan iki ing artikel iki. Upaminipun kita duwe ekspresi lambda sing ora nindakake apa-apa khusus, nanging mung nelpon cara.

x -> System.out.println(x)
Iku nampa sawetara xlan mung telpon System.out.println(), maringaken ing x. Ing kasus iki, kita bisa ngganti karo referensi kanggo cara sing dikarepake. Kaya iki:

System.out::println
Bener - ora ana tanda kurung ing pungkasan! Iki conto sing luwih lengkap:

List<String> strings = new LinkedList<>(); 

strings.add("Dota"); 
strings.add("GTA5"); 
strings.add("Halo"); 

strings.forEach(x -> System.out.println(x));
Ing baris pungkasan, kita nggunakake forEach()cara, kang njupuk obyek sing ngleksanakake Consumerantarmuka. Maneh, iki minangka antarmuka fungsional, mung duwe siji void accept(T t)cara. Patut, kita nulis ekspresi lambda sing nduweni siji parameter (amarga diketik ing antarmuka dhewe, kita ora nemtokake jinis parameter; kita mung nuduhake yen kita bakal ngarani x). Ing awak ekspresi lambda, kita nulis kode sing bakal dieksekusi nalika accept()metode kasebut diarani. Ing kene kita mung nampilake apa sing ana ing xvariabel kasebut. Iki forEach()cara padha iterates liwat kabeh unsur ing koleksi lan nelpon accept()cara ing implementasine sakaConsumerantarmuka (lambda kita), maringaken ing saben item ing koleksi. Kaya sing dakkandhakake, kita bisa ngganti ekspresi lambda kasebut (sing mung ngelasake metode sing beda) kanthi referensi kanggo metode sing dikarepake. Banjur kode kita bakal katon kaya iki:

List<String> strings = new LinkedList<>(); 

strings.add("Dota"); 
strings.add("GTA5"); 
strings.add("Halo");

strings.forEach(System.out::println);
Sing utama yaiku paramèter println()lan accept()metode cocog. Amarga println()cara bisa nampa apa (iku overloaded kanggo kabeh jinis primitif lan kabeh obyek), tinimbang lambda expression, kita mung bisa pass referensi kanggo cara println()kanggo forEach(). Banjur forEach()bakal njupuk saben unsur ing koleksi lan pass langsung menyang println()cara. Kanggo sapa wae sing nemoni iki kanggo pisanan, elinga yen kita ora nelpon System.out.println()(kanthi titik ing antarane tembung lan nganggo tanda kurung ing pungkasan). Nanging, kita menehi referensi kanggo metode iki. Yen kita nulis iki

strings.forEach(System.out.println());
kita bakal duwe kesalahan kompilasi. Sadurunge nelpon kanggo forEach(), Jawa weruh sing System.out.println()lagi disebut, supaya mangertèni sing Nilai bali voidlan bakal nyoba kanggo pass voidkanggo forEach(), kang tinimbang dikarepake Consumerobyek.

Sintaks kanggo referensi metode

Iku cukup prasaja:
  1. Kita ngirim referensi menyang cara statis kaya iki:ClassName::staticMethodName

    
    public class Main { 
    
        public static void main(String[] args) { 
    
            List<String> strings = new LinkedList<>(); 
            strings.add("Dota"); 
            strings.add("GTA5"); 
            strings.add("Halo"); 
    
            strings.forEach(Main::staticMethod); 
        } 
    
        private static void staticMethod(String s) { 
    
            // Do something 
        } 
    }
    
  2. Kita ngirim referensi menyang cara non-statis nggunakake obyek sing wis ana, kaya iki:objectName::instanceMethodName

    
    public class Main { 
    
        public static void main(String[] args) { 
    
            List<String> strings = new LinkedList<>();
            strings.add("Dota"); 
            strings.add("GTA5"); 
            strings.add("Halo"); 
    
            Main instance = new Main(); 
            strings.forEach(instance::nonStaticMethod); 
        } 
    
        private void nonStaticMethod(String s) { 
    
            // Do something 
        } 
    }
    
  3. Kita ngliwati referensi kanggo metode non-statis nggunakake kelas sing ngetrapake kaya ing ngisor iki:ClassName::methodName

    
    public class Main { 
    
        public static void main(String[] args) { 
    
            List<User> users = new LinkedList<>(); 
            users.add (new User("John")); 
            users.add(new User("Paul")); 
            users.add(new User("George")); 
    
            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. Kita ngirim referensi menyang konstruktor kaya iki:ClassName::new

    Referensi metode trep banget yen sampeyan wis duwe metode sing bisa digunakake kanthi sampurna minangka callback. Ing kasus iki, tinimbang nulis ekspresi lambda sing ngemot kode metode, utawa nulis ekspresi lambda sing mung nyebut metode kasebut, kita mung ngirim referensi kasebut. Lan mekaten.

Bedane menarik antarane kelas anonim lan ekspresi lambda

Ing kelas anonim, thistembung kunci nuduhake obyek saka kelas anonim. Nanging yen kita nggunakake iki nang lambda a, kita entuk akses menyang obyek saka kelas ngemot. Ing ngendi kita nulis ekspresi lambda. Iki kedadeyan amarga ekspresi lambda diklumpukake dadi metode pribadi ing kelas sing ditulis. Aku ora nyaranake nggunakake "fitur" iki, amarga duwe efek samping lan mbantah prinsip program fungsional. Sing jarene, pendekatan iki konsisten karo OOP. ;)

Ngendi aku entuk informasi lan apa maneh sing kudu diwaca?

Lan, mesthi, aku nemokake akeh barang ing Google :)
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION