Apakah pengenalan notasi lambda baru (lihat misalnya artikel ini ) di Java 8 akan memerlukan beberapa jenis inferensi?
Jika demikian, bagaimana sistem tipe baru akan berdampak pada bahasa Java secara keseluruhan?
Apakah pengenalan notasi lambda baru (lihat misalnya artikel ini ) di Java 8 akan memerlukan beberapa jenis inferensi?
Jika demikian, bagaimana sistem tipe baru akan berdampak pada bahasa Java secara keseluruhan?
Jawaban:
Ada sedikit informasi yang salah dalam jawaban ratchet freak dan di utas komentarnya. Saya akan menjawab di sini dalam jawaban, karena komentar terlalu kecil. Juga, karena ini adalah jawaban, saya akan berusaha menjawab pertanyaan aslinya juga. (Namun perlu dicatat bahwa saya bukan ahli sistem tipe.)
Pertama, jawaban singkat untuk pertanyaan awal adalah Ya dan Tidak. Ya, Java 8 akan memiliki inferensi tipe yang jauh lebih banyak daripada Java 7, dan Tidak, tidak ada sistem tipe "baru" di Java 8, meskipun ada beberapa perubahan kecil .
Java 8 masih akan diketik secara statis, dan itu masih akan memiliki dikotomi antara kelas dan antarmuka. Tidak ada tipe baru seperti tipe fungsi. Jenis lambda pada dasarnya adalah "antarmuka fungsional" yang merupakan antarmuka biasa dengan metode abstrak tunggal.
Antarmuka sekarang dapat memiliki kode dalam bentuk metode default, tetapi model pewarisan tunggal kelas dan pewarisan berganda antarmuka tetap sama. Ada beberapa penyesuaian, tentu saja, seperti aturan untuk penyelesaian metode di hadapan metode default, tetapi fundamentalnya tidak berubah.
Tipe apa pun yang disimpulkan berdasarkan inferensi tipe dapat dituliskan secara eksplisit. Untuk menggunakan contoh ratchet freak ,
Collections.<MyClass>sort(list, (a, b) -> { return a.order - b.order; });
pada dasarnya gula untuk
Collections.<MyClass>sort(list,
(Comparator<MyClass>)((MyClass a, MyClass b) -> { return a.order - b.order; }));
Jadi pernyataan sparkleshy "inferensi tipe tidak memerlukan ekstensi dari sistem tipe" pada dasarnya benar.
Tetapi untuk kembali ke gula sintaksis, saya akan mengulangi pernyataan saya bahwa ekspresi lambda bukanlah gula sintaksis untuk kelas batin anonim. Ratchet freak menyatakan bahwa ekspresi lambda diterjemahkan ke dalam instantiasi kelas dalam anonim, dan Sparkleshy hanya menegaskan kembali bahwa lambda adalah gula sintaksis untuk kelas dalam anonim, tetapi pernyataan ini tidak benar. Mereka mungkin didasarkan pada informasi yang sudah ketinggalan zaman. Implementasi lambda awal memang mengimplementasikan lambda dengan cara ini, tetapi banyak hal telah berubah.
Ekspresi Lambda secara semantik berbeda dari kelas dalam, dan mereka diimplementasikan secara berbeda dari kelas dalam.
Ekspresi Lambda secara semantik berbeda dari kelas dalam dalam beberapa cara. Mengevaluasi ekspresi lambda tidak perlu membuat instance baru setiap kali. Mereka juga memiliki semantik menangkap yang berbeda, misalnya, mereka menangkap ini secara berbeda. Dalam kelas batin, ini adalah instance kelas dalam, sedangkan dalam lambda, ini adalah contoh terlampir. Pertimbangkan yang berikut ini:
public class CaptureThis {
void a(Runnable r) { r.run(); }
void b() {
a(new Runnable() { public void run() { System.out.println(this); }});
a(() -> System.out.println(this));
}
public String toString() { return "outer"; }
public static void main(String[] args) { new CaptureThis().b(); }
}
Dalam JDK 8 lambda build baru-baru ini (saya menggunakan b69 ), hasilnya akan seperti berikut:
CaptureThis$1@113de03
outer
Lebih jauh, ekspresi lambda diimplementasikan sepenuhnya berbeda dari kelas dalam. Jika Anda membandingkan keluaran yang dibongkar, Anda akan melihat bahwa kode kelas dalam langsung mengkompilasi ke penciptaan dan memanggil ke konstruktor dari CaptureThis $ 1, sedangkan ekspresi lambda mengkompilasi ke instruksi invokedynamic yang mendapatkan Runnable melalui cara yang tidak ditentukan. Untuk penjelasan lengkap tentang bagaimana ini bekerja dan mengapa, lihat Brian Goetz 'JavaOne 2012 bicara Lambda: A Peek Under The Hood .
this
denganMyClass.this