nsv_productdetail.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
int bottomMargin = ((ViewGroup.MarginLayoutParams) nsv_productdetail.getLayoutParams()).bottomMargin;
nsv_productdetail.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
});
Jika kod di atas ditukar kepada lambda, ini akan menghala ke kelas luaran dan pendengar tidak boleh dialih keluar pada masa ini.
Jadi saya ingin bertanya, bagaimanakah kelas dalaman tanpa nama (kelas dalaman tanpa nama yang boleh ditukar kepada lambda) boleh memperoleh dirinya dalam lambda?
Ganti beberapa kelas dalam tanpa nama
Bahagian ini akan memperkenalkan cara menggunakan ungkapan Lambda untuk memudahkan penulisan kelas dalam tanpa nama Walau bagaimanapun, ekspresi Lambda tidak boleh menggantikan semua kelas dalam tanpa nama. Jangan risau tentang butirannya lagi, mari lihat beberapa contoh.
Contoh 1: Singkatan fungsi tanpa parameter
Jika anda perlu mencipta utas baharu, cara penulisan biasa adalah seperti ini:
// kaedah penulisan kelas dalaman tanpa nama JDK7
Thread baharu(new Runnable(){// nama antara muka
}).start();
Kod di atas menghantar objek Runnable tanpa nama ke kelas Tread dan melebihkan kaedah run() antara muka Runnable untuk melaksanakan logik yang sepadan. Ini adalah cara penulisan biasa dalam JDK7 dan sebelum ini. Kelas dalaman tanpa nama menjimatkan masalah untuk menamakan kelas, tetapi ia masih tidak cukup mudah dalam Java 8, ia boleh dipermudahkan kepada bentuk berikut:
// Cara menulis ungkapan JDK8 Lambda
Benang baharu(
).start();
Kod di atas mempunyai fungsi yang sama seperti kelas dalam tanpa nama, tetapi ia lebih jauh daripada kelas dalam tanpa nama. Di sini nama sambungan dan nama fungsi ditinggalkan bersama-sama, menjadikannya lebih menyegarkan untuk menulis. Jika badan fungsi mempunyai beberapa baris, ia boleh disertakan dengan pendakap kerinting, seperti ini:
// Cara menulis blok kod ungkapan Lambda JDK8
Benang baharu(
).start();
Contoh 2: Singkatan fungsi dengan parameter
Jika anda ingin menghantar pembanding tersuai ke senarai rentetan dan mengisihnya mengikut panjang rentetan, bentuk penulisan Java 7 adalah seperti berikut:
// Cara menulis kelas dalaman tanpa nama dalam JDK7
List<String> list = Arrays.asList("I", "love", "you", "too");
Collections.sort(list, new Comparator<String> ;() {//Nama antara muka
});
Kod di atas membebankan kaedah compare() antara muka Comparator melalui kelas dalam untuk melaksanakan logik perbandingan. Menggunakan ungkapan Lambda boleh dipendekkan seperti berikut:
// Cara menulis ungkapan JDK8 Lambda
List<String> list = Arrays.asList("I", "love", "you", "too");
Collections.sort(list, (s1, s2) - > ;{// Abaikan jenis jadual parameter
});
Kod di atas mempunyai fungsi yang sama seperti kelas dalaman tanpa nama. Selain meninggalkan nama antara muka dan nama kaedah, jenis jadual parameter juga ditinggalkan dalam kod. Ini adalah disebabkan oleh mekanisme inferens jenis javac Pengkompil boleh membuat kesimpulan jenis parameter berdasarkan maklumat kontekstual. Ambil perhatian bahawa Java ialah bahasa yang ditaip kuat, dan setiap pembolehubah dan objek mesti mempunyai jenis yang jelas.
Asas untuk singkatan
Mungkin anda sudah fikir bahawa asas untuk menggunakan Lambda ialah mesti ada antara muka berfungsi yang sepadan (antara muka berfungsi merujuk kepada antara muka dengan hanya satu kaedah abstrak di dalamnya). Ini konsisten dengan Java sebagai bahasa yang ditaip kuat, yang bermaksud bahawa anda tidak boleh menulis ungkapan Lambda sewenang-wenangnya di mana-mana dalam kod. Sebenarnya, jenis Lambda ialah jenis yang sepadan dengan antara muka fungsi. Asas lain untuk ungkapan lambda ialah mekanisme inferens jenis Jika maklumat konteks mencukupi, pengkompil boleh membuat kesimpulan jenis jadual parameter tanpa menamakannya secara eksplisit. Lambda menyatakan lebih banyak bentuk bertulis undang-undang seperti berikut:
// Bentuk tulisan Lambda
Larian boleh dijalankan = () -> System.out.println("Hello World");// 1
ActionListener listener = event -> System.out.println("button clicked " );// 2
Barisan berbilang boleh dijalankan = () -> {// 3 blok kod
};
Antara muka fungsi tersuai adalah mudah, anda hanya perlu menulis antara muka dengan hanya satu kaedah abstrak.BinaryOperator<Long> tambah = (Panjang x, Long y) -> menunjukkan singkatan bagi fungsi tanpa parameter;
Antara muka fungsi tersuai
// Antara muka fungsi tersuai
antara muka awam ConsumerInterface<T>{
}@FunctionalInterface dalam kod di atas adalah pilihan, tetapi menambahkan anotasi ini pengkompil akan membantu anda menyemak sama ada antara muka mematuhi spesifikasi antara muka berfungsi. Sama seperti menambah anotasi @Override akan menyemak sama ada fungsi tersebut terlebih beban.
Dengan definisi antara muka di atas, anda boleh menulis kod yang serupa dengan yang berikut:
ConsumerInterface<String> pengguna = str -> System.out.println(str);
Seterusnya, anda juga boleh menggunakannya seperti ini:
kelas MyStream<T>{
}
MyStream<String> strim = MyStream<String>();stream.myForEach(str -> System.out.println(str));// Gunakan antara muka fungsi tersuai untuk menulis ungkapan Lambda
Apa yang tidak boleh dilakukan ialah Lambda itu sendiri bukan objek.