Membaca di spec Java-8, saya terus melihat referensi ke 'tipe SAM'. Saya belum dapat menemukan penjelasan yang jelas tentang apa ini.
Apa itu tipe SAM dan apa contoh skenario kapan seseorang bisa digunakan?
Membaca di spec Java-8, saya terus melihat referensi ke 'tipe SAM'. Saya belum dapat menemukan penjelasan yang jelas tentang apa ini.
Apa itu tipe SAM dan apa contoh skenario kapan seseorang bisa digunakan?
Jawaban:
Untuk meringkas link Jon diposting 1 dalam kasus itu pernah turun, "SAM" singkatan dari "metode abstrak tunggal", dan "SAM-tipe" mengacu pada interface seperti Runnable
, Callable
, dll ekspresi Lambda, fitur baru di Jawa 8, yang dianggap sebagai tipe SAM dan dapat secara bebas dikonversi ke mereka.
Misalnya, dengan antarmuka seperti ini:
public interface Callable<T> {
public T call();
}
Anda dapat mendeklarasikan Callable
ekspresi lambda yang menggunakan seperti ini:
Callable<String> strCallable = () -> "Hello world!";
System.out.println(strCallable.call()); // prints "Hello world!"
Ekspresi Lambda dalam konteks ini sebagian besar hanya gula sintaksis. Mereka terlihat lebih baik dalam kode daripada kelas anonim dan kurang membatasi penamaan metode. Ambil contoh ini dari tautan:
class Person {
private final String name;
private final int age;
public static int compareByAge(Person a, Person b) { ... }
public static int compareByName(Person a, Person b) { ... }
}
Person[] people = ...
Arrays.sort(people, Person::compareByAge);
Ini menciptakan Comparator
penggunaan metode tertentu yang tidak berbagi nama yang sama denganComparator.compare
, sehingga Anda tidak harus mengikuti penamaan antarmuka metode dan Anda dapat memiliki beberapa pembandingan perbandingan dalam suatu kelas, kemudian membuat pembanding dengan cepat ekspresi lambda.
Lebih dalam ...
Pada level yang lebih dalam, Java mengimplementasikan ini menggunakan invokedynamic
instruksi bytecode yang ditambahkan di Java 7. Saya katakan sebelumnya bahwa mendeklarasikan Lambda menciptakan instance Callable
atau Comparable
mirip dengan kelas anonim, tetapi itu tidak sepenuhnya benar. Sebagai gantinya, pertama kali invokedynamic
dipanggil, ia menciptakan fungsi pengendali Lambda menggunakan LambdaMetafactory.metafactory
metode , kemudian menggunakan contoh ini di-cache dalam doa selanjutnya dari Lambda. Info lebih lanjut dapat ditemukan dalam jawaban ini .
Pendekatan ini kompleks dan bahkan termasuk kode yang dapat membaca nilai-nilai primitif dan referensi langsung dari memori tumpukan untuk masuk ke kode Lambda Anda (misalnya untuk berkeliling perlu mengalokasikan Object[]
array untuk memanggil Lambda Anda), tetapi memungkinkan iterasi implementasi Lambda di masa mendatang. untuk mengganti implementasi lama tanpa harus khawatir tentang kompatibilitas bytecode. Jika para insinyur di Oracle mengubah implementasi Lambda yang mendasari dalam versi JVM yang lebih baru, Lambdas yang dikompilasi pada JVM yang lebih lama akan secara otomatis menggunakan implementasi yang lebih baru tanpa perubahan apa pun pada bagian pengembang.
1 Sintaks pada tautan sudah kedaluwarsa. Lihatlah Lambda Expressions Java Trail untuk melihat sintaks saat ini.