Variabel yang digunakan dalam ekspresi lambda harus final atau efektif final
Ketika saya mencoba menggunakannya calTz
menunjukkan kesalahan ini.
private TimeZone extractCalendarTimeZoneComponent(Calendar cal, TimeZone calTz) {
try {
cal.getComponents().getComponents("VTIMEZONE").forEach(component -> {
VTimeZone v = (VTimeZone) component;
v.getTimeZoneId();
if (calTz == null) {
calTz = TimeZone.getTimeZone(v.getTimeZoneId().getValue());
}
});
} catch (Exception e) {
log.warn("Unable to determine ical timezone", e);
}
return null;
}
calTz
dari lambda.Jawaban:
Sebuah
final
cara variabel yang dapat dipakai hanya satu kali. di Java Anda tidak bisa menggunakan variabel non-final di lambda juga di kelas dalam anonim.Anda dapat memperbaiki kode Anda dengan yang lama untuk setiap loop:
Bahkan jika saya tidak mengerti beberapa bagian dari kode ini:
v.getTimeZoneId();
tanpa menggunakan nilai baliknyacalTz = TimeZone.getTimeZone(v.getTimeZoneId().getValue());
Anda tidak mengubah yang semula disahkancalTz
dan Anda tidak menggunakannya dalam metode ininull
, mengapa Anda tidak menetapkanvoid
sebagai tipe pengembalian?Semoga juga tips ini membantu Anda untuk meningkatkan.
sumber
Meskipun jawaban lain membuktikan persyaratan, mereka tidak menjelaskan mengapa persyaratan itu ada.
JLS menyebutkan mengapa dalam §15.27.2 :
Untuk menurunkan risiko bug, mereka memutuskan untuk memastikan variabel yang ditangkap tidak pernah bermutasi.
sumber
Dari lambda, Anda tidak bisa mendapatkan referensi ke apa pun yang belum final. Anda harus mendeklarasikan pembungkus akhir dari luar lamda untuk menyimpan variabel Anda.
Saya telah menambahkan objek 'referensi' terakhir sebagai pembungkus ini.
sumber
reference.set(calTz);
atau referensi harus dibuat menggunakannew AtomicReference<>(calTz)
, jika tidak TimeZone non-nol yang disediakan sebagai parameter akan hilang.Java 8 memiliki konsep baru yang disebut variabel "Final efektif". Ini berarti bahwa variabel lokal non-final yang nilainya tidak pernah berubah setelah inisialisasi disebut "Efektif Final".
Konsep ini diperkenalkan karena sebelum Java 8 , kami tidak dapat menggunakan variabel lokal non-final dalam kelas anonim . Jika Anda ingin memiliki akses ke variabel lokal di kelas anonim , Anda harus membuatnya final.
Ketika lambda diperkenalkan, pembatasan ini dikurangi. Oleh karena itu kebutuhan untuk membuat variabel lokal final jika tidak diubah setelah diinisialisasi sebagai lambda itu sendiri tidak lain adalah kelas anonim.
Java 8 menyadari sulitnya mendeklarasikan variabel lokal final setiap kali pengembang menggunakan lambda, memperkenalkan konsep ini, dan membuatnya tidak perlu untuk membuat variabel lokal final. Jadi jika Anda melihat aturan untuk kelas anonim tidak berubah, hanya saja Anda tidak perlu menulis
final
kata kunci setiap kali menggunakan lambdas.Saya menemukan penjelasan yang bagus di sini
sumber
effectively final
bukan kode, itu terminologi. Lihat Kapan pemformatan kode harus digunakan untuk teks bukan kode? pada Meta Stack Overflow .final
kata kunci" adalah kata kode dan benar untuk memformat seperti itu, tetapi ketika Anda menggunakan "final" secara deskriptif daripada sebagai kode, itu terminologi sebagai gantinya).Dalam contoh Anda, Anda dapat mengganti
forEach
lamdba denganfor
loop sederhana dan memodifikasi variabel apa pun secara bebas. Atau, mungkin, perbaiki kode Anda sehingga Anda tidak perlu memodifikasi variabel apa pun. Namun, saya akan menjelaskan secara lengkap apa arti kesalahan itu dan bagaimana cara mengatasinya.Spesifikasi Bahasa Java 8, §15.27.2 :
Pada dasarnya Anda tidak dapat mengubah variabel lokal (
calTz
dalam hal ini) dari dalam lambda (atau kelas lokal / anonim). Untuk mencapainya di Java, Anda harus menggunakan objek yang bisa berubah dan memodifikasinya (melalui variabel terakhir) dari lambda. Salah satu contoh objek yang bisa berubah di sini adalah array dari satu elemen:sumber
jika tidak perlu memodifikasi variabel daripada solusi umum untuk masalah seperti ini adalah mengekstraksi bagian kode yang menggunakan lambda dan menggunakan kata kunci terakhir pada metode-parameter.
sumber
Variabel yang digunakan dalam ekspresi lambda harus final atau efektif final, tetapi Anda bisa menetapkan nilai ke array elemen final.
sumber