Kelas Anonim di Jawa

1. Perkenalan

Dalam tutorial ini, kami akan mempertimbangkan kelas anonim di Java.

Kami akan menjelaskan bagaimana kami dapat mendeklarasikan dan membuat contohnya. Kami juga akan membahas properti dan batasannya secara singkat.

2. Deklarasi Kelas Anonim

Kelas anonim adalah kelas dalam tanpa nama. Karena mereka tidak memiliki nama, kami tidak dapat menggunakannya untuk membuat instance kelas anonim. Akibatnya, kita harus mendeklarasikan dan membuat instance kelas anonim dalam satu ekspresi pada titik penggunaan.

Kami dapat memperluas kelas yang ada atau mengimplementasikan antarmuka.

2.1. Memperluas Kelas

Saat kami membuat instance kelas anonim dari yang sudah ada, kami menggunakan sintaks berikut:

Dalam tanda kurung, kami menetapkan parameter yang diperlukan oleh konstruktor kelas yang kami perluas:

new Book("Design Patterns") { @Override public String description() { return "Famous GoF book."; } }

Secara alami, jika konstruktor kelas induk tidak menerima argumen, kita harus membiarkan tanda kurung kosong.

2.2. Menerapkan Antarmuka

Kami juga dapat membuat instance kelas anonim dari antarmuka:

Jelasnya, antarmuka Java tidak memiliki konstruktor, jadi tanda kurung selalu kosong. Ini adalah satu-satunya cara yang harus kita lakukan untuk mengimplementasikan metode antarmuka:

new Runnable() { @Override public void run() { ... } }

Setelah kami membuat instance kelas anonim, kami dapat menetapkan instance itu ke variabel agar dapat merujuknya di suatu tempat nanti.

Kita bisa melakukan ini menggunakan sintaks standar untuk ekspresi Java:

Runnable action = new Runnable() { @Override public void run() { ... } };

Seperti yang telah kami sebutkan, deklarasi kelas anonim adalah sebuah ekspresi, oleh karena itu ia harus menjadi bagian dari sebuah pernyataan . Ini menjelaskan mengapa kami menempatkan titik koma di akhir pernyataan.

Jelas, kita dapat menghindari menugaskan instance ke variabel jika kita membuat instance itu secara inline:

List actions = new ArrayList(); actions.add(new Runnable() { @Override public void run() { ... } });

Kita harus menggunakan sintaks ini dengan sangat hati-hati karena dapat dengan mudah mengalami kesulitan membaca kode terutama ketika implementasi metode run () membutuhkan banyak ruang.

3. Properti Kelas Anonim

Ada kekhususan tertentu dalam menggunakan kelas anonim sehubungan dengan kelas tingkat atas biasa. Di sini kami secara singkat menyentuh masalah yang paling praktis. Untuk informasi paling tepat dan terbaru, kami selalu dapat melihat Spesifikasi Bahasa Java.

3.1. Pembuat

Sintaks kelas anonim tidak memungkinkan kita untuk membuatnya mengimplementasikan banyak antarmuka. Selama konstruksi, mungkin ada satu contoh dari kelas anonim . Oleh karena itu, mereka tidak pernah bisa menjadi abstrak. Karena mereka tidak punya nama, kami tidak bisa memperpanjangnya. Untuk alasan yang sama, kelas anonim tidak dapat secara eksplisit mendeklarasikan konstruktor.

Faktanya, tidak adanya konstruktor tidak mewakili masalah apa pun bagi kami karena alasan berikut:

  1. kami membuat instance kelas anonim pada saat yang sama saat kami mendeklarasikannya
  2. dari contoh kelas anonim, kita dapat mengakses variabel lokal dan menyertakan anggota kelas

3.2. Anggota Statis

Kelas anonim tidak dapat memiliki anggota statis kecuali yang konstan.

Misalnya, ini tidak akan bisa dikompilasi:

new Runnable() { static final int x = 0; static int y = 0; // compilation error! @Override public void run() {...} };

Sebaliknya, kita akan mendapatkan error berikut:

The field y cannot be declared static in a non-static inner type, unless initialized with a constant expression

3.3. Ruang Lingkup Variabel

Kelas anonim menangkap variabel lokal yang berada dalam lingkup blok tempat kita mendeklarasikan kelas:

int count = 1; Runnable action = new Runnable() { @Override public void run() { System.out.println("Runnable with captured variables: " + count); } }; 

Seperti yang kita lihat, jumlah variabel lokal dan tindakan didefinisikan dalam blok yang sama. Untuk alasan ini, kita dapat mengakses hitungan dari dalam deklarasi kelas.

Perhatikan bahwa untuk dapat menggunakan variabel lokal, variabel tersebut harus final secara efektif. Sejak JDK 8, tidak diperlukan lagi kita mendeklarasikan variabel dengan kata kunci final . Meskipun demikian, variabel tersebut harus final . Jika tidak, kami mendapatkan kesalahan kompilasi:

[ERROR] local variables referenced from an inner class must be final or effectively final

Agar kompilator memutuskan bahwa sebuah variabel, pada kenyataannya, tidak dapat diubah, dalam kode, seharusnya hanya ada satu tempat di mana kita menetapkan nilai padanya. Kami mungkin menemukan lebih banyak informasi tentang variabel akhir yang efektif dalam artikel kami "Mengapa Variabel Lokal yang Digunakan di Lambdas Harus Final atau Secara Efektif Final?"

Mari kita sebutkan bahwa karena setiap kelas dalam, kelas anonim dapat mengakses semua anggota kelas yang melingkupinya .

4. Kasus Penggunaan Kelas Anonim

Mungkin ada berbagai macam aplikasi kelas anonim. Mari jelajahi beberapa kemungkinan kasus penggunaan.

4.1. Hirarki dan Enkapsulasi Kelas

We should use inner classes in general use cases and anonymous ones in very specific ones in order to achieve a cleaner hierarchy of classes in our application. When using inner classes, we may achieve a finer encapsulation of the enclosing class's data. If we define the inner class functionality in a top-level class, then the enclosing class should have public or package visibility of some of its members. Naturally, there are situations when it is not very appreciated or even accepted.

4.2. Cleaner Project Structure

We usually use anonymous classes when we have to modify on the fly the implementation of methods of some classes. In this case, we can avoid adding new *.java files to the project in order to define top-level classes. This is especially true if that top-level class would be used just one time.

4.3. UI Event Listeners

In applications with a graphical interface, the most common use case of anonymous classes is to create various event listeners. For example, in the following snippet:

button.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { ... } }

we create an instance of an anonymous class that implements interface ActionListener. Its actionPerformed method gets triggered when a user clicks the button.

Since Java 8, lambda expressions seem to be a more preferred way though.

5. General Picture

Kelas anonim yang kami pertimbangkan di atas hanyalah kasus kelas bertingkat tertentu. Umumnya, kelas bersarang adalah kelas yang dideklarasikan di dalam kelas atau antarmuka lain :

Melihat diagram, kita melihat bahwa kelas anonim bersama dengan anggota lokal dan nonstatis membentuk apa yang disebut kelas dalam . Bersama dengan kelas anggota statis , mereka membentuk kelas bertingkat.

6. Kesimpulan

Pada artikel ini, kami telah mempertimbangkan berbagai aspek kelas anonim Java. Kami juga telah menjelaskan hierarki umum kelas bertingkat.

Seperti biasa, kode lengkap tersedia di repositori GitHub kami.