Rumah >Java >javaTutorial >Ringkasan kemahiran Java: Cara membaca kod sumber Lambda

Ringkasan kemahiran Java: Cara membaca kod sumber Lambda

WBOY
WBOYke hadapan
2022-04-18 18:13:501546semak imbas

Artikel ini membawakan anda pengetahuan yang berkaitan tentang java Ia terutamanya memperkenalkan isu berkaitan tentang cara melihat kod sumber Lambda menggunakan ungkapan Lambda boleh membuat banyak pengoptimuman banyak perkara dengan hanya satu baris kod. Mari kita lihat. Saya harap ia akan membantu semua orang.

Ringkasan kemahiran Java: Cara membaca kod sumber Lambda

Pembelajaran yang disyorkan: "tutorial video java"

Semua orang tahu bahawa ungkapan Lambda ditambah dalam Java8, gunakan ungkapan Lambda Formula boleh mengoptimumkan kod dengan banyak, dan anda boleh melakukan banyak perkara dengan hanya beberapa baris kod Bab ini mengambil Lambda sebagai contoh Bahagian pertama menerangkan prinsip pelaksanaan asasnya, dan bahagian kedua menerangkan postur biasa Lambda. aliran dalam kerja.

1. Demo

Mula-mula kita melihat demo ekspresi Lambda, seperti yang ditunjukkan di bawah:

Kod ini agak mudah, cuma mulakan utas baru dan cetak ayat, tetapi untuk kod dalam gambar () -> System.out.println (“ lambda is run “), saya rasa ramai pelajar keliru Java Adakah anda mengenali kod ini?

Jika kita menukar tulisan kepada kelas dalaman tanpa nama, ia akan menjadi sangat jelas dan semua orang boleh memahaminya, seperti yang ditunjukkan di bawah:

Adakah itu bermakna ( ) -> System.out.println (“ lambda dijalankan “) Adakah bentuk kod ini sebenarnya mencipta kelas dalam? Sebenarnya, ini adalah ungkapan Lambda yang paling mudah Kami tidak dapat melihat kod sumber dan struktur asasnya melalui IDEA Di sini kami akan memperkenalkan beberapa cara untuk melihat pelaksanaan asasnya.

2. Kaedah penghakiman pengecualian

Kami boleh secara aktif membuang pengecualian semasa pelaksanaan kod dan mencetak timbunan akan menerangkan trajektori berjalan Secara amnya, kaedah ini adalah mudah dan cekap, dan anda pada dasarnya boleh melihat Mari cuba kod tersembunyi dalam banyak kes, seperti yang ditunjukkan di bawah:

Dari timbunan pengecualian, kita dapat melihat bahawa JVM secara automatik mencipta kelas dalaman untuk semasa class ($ muncul beberapa kali dalam timbunan ralat menunjukkan kelas dalaman semasa pelaksanaan kod kelas dalaman, pengecualian dilemparkan, tetapi kod yang ditunjukkan di sini adalah Sumber Tidak Diketahui, jadi kami tidak boleh menyahpepijatnya dalam keadaan biasa , pengecualian Kedua-dua kaedah boleh mendedahkan laluan pelaksanaan kod Kami boleh menetapkan titik putus dan berjalan semula Namun, untuk ungkapan Lambda, melalui kaedah penghakiman pengecualian, kami hanya tahu bahawa terdapat kelas dalaman, tetapi kami tidak dapat melihat kod sumber dalam dalaman. kelas.

3. kaedah arahan javap

javap ialah alat Java sendiri yang boleh melihat fail bytecode kelas Komputer yang telah memasang persekitaran asas Java boleh terus melaksanakan arahan javap, seperti yang ditunjukkan di bawah:

Antara pilihan arahan, kami terutamanya menggunakan perintah -v -verbose untuk mengeluarkan sepenuhnya kandungan fail bytecode.

Seterusnya kami menggunakan arahan javap untuk melihat fail Lambda.class Semasa penerangan, kami akan membawa sedikit pengetahuan tentang fail kelas.

Kami mencari lokasi Lambda.class dalam tetingkap arahan, jalankan arahan: javap -verbose Lambda.class, dan kemudian anda akan melihat senarai panjang perkara, ini dipanggil arahan pemasangan, mari lakukannya seterusnya Biar saya terangkan (semua bahan rujukan datang daripada Spesifikasi Mesin Maya Java, dan tidak akan dipetik satu persatu):

Dalam arahan pemasangan, kita boleh mencari senarai panjang jenis dengan mudah bermula dengan kolam Constant . Kami memanggilnya kumpulan malar Ia dipanggil Run-Time Constant Pool dalam bahasa Inggeris Kami hanya memahaminya sebagai jadual yang diisi dengan pemalar , dsb. Setiap elemen dalam jadual dipanggil cp

infomaklumat terdiri daripada nama pengenalan (tag) yang unik Pada masa ini, terdapat sejumlah jenis teg:

Ringkasan kemahiran Java: Cara membaca kod sumber Lambda.

pelekat Berikut adalah sebahagian daripada gambar yang kami huraikan:

  1. Perkataan Kolam Malar dalam gambar bermaksud maklumat semasa ialah kolam malar ;

  2. Setiap baris ialah

    , #1 dalam lajur pertama mewakili kedudukan bertanda 1 dalam kumpulan malar;

  3. Lajur kedua bagi setiap baris ialah pengecam unik (teg) cp_info Contohnya, Methodref sepadan dengan CONSTANT_Methodref dalam jadual di atas (nilai dalam jadual di atas sepadan dengan teg bagi. 10), Mewakili baris semasa dan mewakili maklumat perihalan kaedah, seperti nama kaedah, jenis parameter input, jenis parameter output, dll. Makna khusus boleh didapati dalam spesifikasi mesin maya Java Methodref adalah seperti berikut:
    Ringkasan kemahiran Java: Cara membaca kod sumber Lambda

  4. Dalam lajur ketiga setiap baris, jika ia adalah nilai tertentu, nilai khusus akan dipaparkan secara langsung nilai kompleks, rujukan kepada cp_info akan dipaparkan, contohnya Merah 2 dalam rajah merujuk kepada dua cp_info pada kedudukan 13 dan 14. 13 bermakna nama kaedah ialah init, dan 14 bermakna kaedah tidak mempunyai nilai pulangan. Gabungan nama dan jenis pulangan kaedah mewakili pembina tanpa parameter;

  5. Untuk jenis cp_info yang lebih penting, kami menerangkan maksudnya:

InvokeDynamic mewakili kaedah panggilan dinamik, yang akan kami terangkan secara terperinci kemudian; >

Fieldref mewakili maklumat perihalan medan, seperti nama dan jenis medan; nama kolektif untuk kaedah panggilan secara dinamik, disusun semasa penyusunan Kami tidak tahu kaedah mana yang khusus pada masa itu, tetapi kami pasti akan mengetahui kaedah mana yang dipanggil semasa runtime; , dan kami hanya akan mengetahui jenis kaedahnya apabila berjalan secara dinamik.

  1. Daripada tiga tempat yang bertanda merah dalam gambar di atas, kami mendapati bahawa Ljava/lang/invoke/MethodHandles$Lookup, java/lang/invoke/LambdaMetafactory.metafactory, kod serupa seperti ini, MethodHandles dan LambdaMetafactory adalah kedua-dua kaedah Penting di bawah pakej java.lang.invoke terutamanya melaksanakan fungsi bahasa dinamik Kita tahu bahawa bahasa java ialah bahasa yang disusun secara statik. dsb. telah ditentukan, dan invoke melaksanakan bahasa dinamik, yang bermaksud bahawa jenis kelas, kaedah dan medan tidak diketahui semasa menyusun, dan hanya diketahui semasa dijalankan.
  2. Contohnya, baris kod ini: Runnable runnable = () -> System.out.println(“lambda is run”); does , hanya apabila berjalan anda akan tahu bahawa ini mewakili kaedah Runnable.run(). Banyak kelas dalam pakej invoke direka untuk mewakili ini (), yang kami panggil kaedah mengendalikan (MethodHandler, pengkompil hanya tahu bahawa ini adalah kaedah pengendalian, dan tidak tahu kaedah yang sebenarnya saya lakukan). tidak tahu sehingga masanya, jadi persoalannya ialah, apabila JVM melaksanakan, bagaimanakah ia tahu bahawa pengendalian kaedah () sebenarnya melaksanakan kaedah Runnable.run()?
  3. Pertama, mari kita lihat arahan pemasangan kaedah mudah:
  4. Daripada gambar di atas, anda boleh melihat () -> Sistem dalam kaedah ringkas () dalam kod out.println("lambda is run") sebenarnya ialah kaedah Runnable.run.

Kami menjejak kembali ke kolam pemalar #2, iaitu 1 merah dalam gambar di atas menunjukkan bahawa ini ialah panggilan dinamik ialah cp_info daripada dua kumpulan malar. 0:#37 Kami Melihat ke bawah untuk #37, yang bermaksud // run:()Ljava/lang/Runnable Ini menunjukkan bahawa apabila JVM sebenarnya dilaksanakan, kaedah Runnable.run() perlu dipanggil secara dinamik arahan pemasangan, kita dapat melihat bahawa () Sebenarnya, ia adalah Runnable.run().

Kami menemui perkataan LambdaMetafactory.metafactory di 3 tempat dalam gambar di atas Dengan menyoal dokumentasi rasmi, kami mengetahui bahawa kaedah ini adalah kunci untuk memautkan kod sebenar semasa pelaksanaan, jadi kami menaipnya di dalam. kaedah metafactory. Nyahpepijat dengan titik putus, seperti yang ditunjukkan di bawah:

Pemanggil parameter input kaedah metafaktor mewakili lokasi sebenar panggilan dinamik, invokedName mewakili nama kaedah panggilan , dan invokedType mewakili berbilang input bagi panggilan Dari segi parameter dan parameter output, samMethodType mewakili parameter pelaksana tertentu, implMethod mewakili pelaksana sebenar dan instantiatedMethodType adalah bersamaan dengan implMethod.

Ringkasan perkara di atas:

1: Daripada kaedah mudah arahan pemasangan, kita dapat melihat bahawa kaedah Runnable.run akan dilaksanakan

2: Dalam operasi sebenar Apabila JVM menemui arahan invokedynamic bagi kaedah mudah, ia akan secara dinamik memanggil kaedah LambdaMetafactory.metafactory dan melaksanakan kaedah Runnable.run tertentu.

Jadi pelaksanaan khusus nilai ekspresi Lambda boleh dikaitkan dengan arahan JVM invokedynamic Ia adalah tepat kerana arahan ini walaupun anda tidak tahu apa yang perlu dilakukan semasa menyusun, anda boleh menemui pelaksanaan khusus. apabila berjalan secara dinamik. Ringkasan kemahiran Java: Cara membaca kod sumber Lambda

Kemudian mari kita lihat pada penghujung output arahan pemasangan Kami mendapati kelas dalaman ditemui dalam kaedah penghakiman pengecualian, seperti yang ditunjukkan di bawah:

Ringkasan kemahiran Java: Cara membaca kod sumber Lambda

Terdapat. banyak anak panah dalam gambar di atas Semua maklumat kelas dalaman semasa dinyatakan dengan jelas lapisan demi lapisan.

4. Ringkasan

Mari kita ringkaskan, pelaksanaan ungkapan Lambda bergantung terutamanya pada arahan JVM bagi kelas yang kami tunjukkan ialah: demo.eight.Lambda itu sendiri.

Tanpa berlengah lagi, artikel sudah tamat, menanti siri ketiga!

Pembelajaran yang disyorkan: "tutorial video java"

Atas ialah kandungan terperinci Ringkasan kemahiran Java: Cara membaca kod sumber Lambda. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:csdn.net. Jika ada pelanggaran, sila hubungi admin@php.cn Padam