Teman-teman, seperti yang sudah Anda perhatikan, pada akhir Juni, kami akan memulai banyak grup baru, di antaranya aliran berikutnya dari kursus
"Pengembang Java" , yang disukai semua orang. Saat ini kami sedang berbagi dengan Anda terjemahan baru yang disiapkan untuk siswa kursus ini.

Saat menambahkan fitur baru ke bahasa pemrograman, pengembang bahasa biasanya memperhatikan konflik dengan fitur bahasa saat ini, terhadap perubahan yang menyebabkan ketidakcocokan dengan versi sebelumnya, kesalahan dan situasi apa pun yang dapat menyebabkan perilaku yang tidak terdefinisi atau tidak terduga.
Namun, seringkali mereka tidak cukup memperhatikan perubahan kecil dalam teknik praktis baru untuk menulis kode. Perubahan ini seringkali merupakan efek samping dari fitur baru. Perubahan-perubahan semacam ini bukanlah fitur baru. Ini adalah perubahan halus yang muncul karena fitur lain atau kombinasinya.
Kelas batin anonim
Di Jawa, kelas dalam adalah kelas yang didefinisikan sebagai anggota kelas. Ada empat jenis kelas batin:
- bersarang statis
- internal
- lokal (metode lokal)
- anonim
Kelas dalam anonim adalah kelas tanpa nama yang menyediakan implementasi dari kelas yang ada. Kelas semacam itu banyak digunakan untuk menangani acara dalam pemrograman berorientasi peristiwa. Biasanya kelas dalam anonim menyediakan implementasi on-the-fly dari kelas abstrak. Namun, ini tidak perlu. Kelas batin anonim dapat dibuat dari kelas non-abstrak.
Saya percaya bahwa ada hal yang tidak sepenuhnya dipahami dalam kaitannya dengan kelas batin anonim. Faktanya adalah bahwa pemrogram benar-benar
membuat subkelas dari kelas sumber . Subkelas ini diberi nama
Class$X
, di mana
Class
adalah kelas luar, dan
X
adalah nomor yang mewakili urutan di mana kelas dalam dipakai di kelas luar. Misalnya,
AnonDemo$3
adalah kelas dalam ketiga yang dibuat di
AnonDemo
. Anda tidak dapat memanggil kelas-kelas ini dengan cara biasa. Dan, tidak seperti jenis kelas batin lainnya, kelas dalam anonim selalu secara implisit merupakan anak dari jenis yang darinya ia diciptakan (dengan pengecualian menggunakan
var
, yang akan segera kita lihat).
Mari kita lihat sebuah contoh.
class Anon { }; public class AnonDemo { public static void main (String[] args) { Anon anonInner = new Anon () { public String toString() { return "Overriden"; }; public void doSomething() { System.out.println("Blah"); }; }; System.out.println(anonInner.toString()); anonInner.doSomething();
Dalam contoh ini, kami membuat kelas batin anonim berdasarkan kelas Anon. Intinya, kami
membuat subclass tanpa nama dari kelas tertentu . Sebelum Java 10, kelas-kelas dalam anonim hampir selalu secara implisit bersifat polimorfik. Saya mengatakan "hampir", karena kode non-polimorfik seperti ini, tentu saja, akan dieksekusi.
new Anon() { public void foo() { System.out.println("Woah"); } }.foo();
Namun, jika kita ingin menetapkan hasil pembuatan instance kelas dalam anonim ke tipe asli, maka operasi semacam itu akan bersifat polimorfik. Alasan untuk ini terletak pada kenyataan bahwa kami secara implisit membuat subkelas dari kelas yang kami tentukan sebagai sumber untuk kelas dalam anonim dan kami tidak akan dapat mengakses jenis objek spesifik (
Class$X
) untuk menentukannya dalam kode sumber.
Polimorfisme dan kelas batin anonim, konsekuensi praktis
Apakah Anda memperhatikan kode di atas? Karena kita menggunakan referensi kelas dasar ke objek subclass, menurut hukum polimorfisme kita hanya dapat merujuk ke 1) metode yang didefinisikan oleh kelas dasar atau 2) metode virtual yang ditimpa dalam subclass.
Oleh karena itu, dalam cuplikan kode sebelumnya, memanggil
toString()
untuk objek kelas dalam anonim akan memberi kita nilai "Overridden" yang ditimpa, namun memanggil
doSomething()
akan menghasilkan kesalahan kompilasi. Apa alasannya
Objek subclass dengan referensi ke tipe kelas dasar tidak memiliki akses ke anggota subclass melalui referensi ini ke kelas dasar. Satu-satunya pengecualian untuk aturan ini adalah jika subclass menimpa metode kelas dasar. Dalam kasus ini, Java, sesuai dengan sifat polimorfiknya, menggunakan Metode Pengiriman Dinamis untuk memilih versi metode subkelas virtual saat runtime.
Jika Anda belum tahu,
metode virtual adalah metode yang dapat diganti. Di Jawa, semua metode non-final, non-pribadi dan non-statis adalah virtual secara default. Saya berbicara secara default, dan tidak secara implisit, karena jvm yang berbeda dapat melakukan optimasi yang dapat mengubah ini.
Apa hubungannya Java 10 dengan itu?
Fitur kecil yang disebut inferensi tipe. Lihatlah contoh berikut:
class Anon { }; public class AnonDemo { public static void main(String[] args) { var anonInner = new Anon() { public void hello() { System.out.println( "New method here, and you can easily access me in Java 10!\n" + "The class is: " + this.getClass() ); }; }; anonInner.hello();
Berhasil, kita bisa memanggil
hello()
! Iblis ada dalam perinciannya. Jika Anda terbiasa dengan
var
, maka Anda sudah mengerti apa yang terjadi di sini. Menggunakan nama yang dicadangkan dari tipe
var
,
Java dapat menentukan tipe pasti dari kelas dalam anonim. Oleh karena itu, kita tidak lagi terbatas pada referensi kelas dasar untuk mengakses objek subclass.Apa yang kami lakukan sebelum Java 10 ketika kami membutuhkan referensi ke subkelas?
Bukan rahasia lagi bahwa di masa lalu yang jauh, tetapi tidak dilupakan, ada perdebatan hebat tentang kelas batin. Dan jika ini rahasia, maka ini adalah salah satu rahasia terburuk di dunia. Tidak diragukan lagi, banyak yang tidak akan menyetujui kenyataan bahwa Anda memerlukan referensi yang tepat untuk kelas dalam anonim, karena idenya adalah untuk menghindari menambahkan sampah ke kelas. Kelas anonim harus digunakan untuk melaksanakan kontrak dengan cepat, untuk operasi yang secara logis terkait dengan kelas lain, misalnya, untuk menangani acara. Namun, mungkin, Barbara yang penasaran tidak mencabik hidungnya, dan saya yakin sebagian besar pengembang sangat penasaran. Mungkin merugikan akal sehat!
Sebelum Java 10, kita dapat mencapai efek yang sama menggunakan refleksi, sebagai berikut:
Anon anonInner2 = new Anon() { public void hello() { System.out.println("Woah! "); }; }; anonInner2.getClass().getMethod("hello").invoke(anonInner2);
Sumber lengkap
Bisa bawa
kesini public class VarAnonInner { public static void main (String[] args) throws Exception { var anonInner = new Anon() { public void hello() { System.out.println("New method here, and you can easily access me in Java 10!\n" + "The class is: " + this.getClass() ); }; }; anonInner.hello(); Anon anonInner2 = new Anon() { public void hello() { System.out.println("Woah! "); }; }; anonInner2.getClass().getMethod("hello").invoke(anonInner2); new Anon() { public void hello() { System.out.println("Woah!!! "); }; }.hello();
Kami sedang menunggu komentar Anda, serta mengingat bahwa
webinar gratis di kursus akan berlangsung hari ini pukul 20.00.