Apa gunanya kelas anonim di Jawa? Bisakah kita mengatakan bahwa penggunaan kelas anonim adalah salah satu kelebihan Java?
Apa gunanya kelas anonim di Jawa? Bisakah kita mengatakan bahwa penggunaan kelas anonim adalah salah satu kelebihan Java?
Jawaban:
Dengan "kelas anonim", saya menganggap Anda maksud kelas batin anonim .
Kelas dalam anonim dapat berguna ketika membuat instance dari objek dengan "ekstra" tertentu seperti metode overriding, tanpa harus benar-benar subkelas kelas.
Saya cenderung menggunakannya sebagai jalan pintas untuk melampirkan pendengar acara:
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// do something
}
});
Menggunakan metode ini membuat pengkodean sedikit lebih cepat, karena saya tidak perlu membuat kelas tambahan yang mengimplementasikan ActionListener
- Saya hanya dapat membuat instance kelas batin anonim tanpa benar-benar membuat kelas yang terpisah.
Saya hanya menggunakan teknik ini untuk tugas "cepat dan kotor" di mana membuat seluruh kelas terasa tidak perlu. Memiliki beberapa kelas batin anonim yang melakukan hal yang persis sama harus di refactored ke kelas yang sebenarnya, baik itu kelas batin atau kelas terpisah.
overloading methods
dan tidak overriding methods
?
Kelas dalam anonim secara efektif ditutup, sehingga dapat digunakan untuk meniru ekspresi lambda atau "delegasi". Misalnya, ambil antarmuka ini:
public interface F<A, B> {
B f(A a);
}
Anda dapat menggunakan ini secara anonim untuk membuat fungsi kelas satu di Java. Katakanlah Anda memiliki metode berikut yang mengembalikan angka pertama lebih besar dari pada daftar yang diberikan, atau jika tidak ada angka yang lebih besar:
public static int larger(final List<Integer> ns, final int i) {
for (Integer n : ns)
if (n > i)
return n;
return i;
}
Dan kemudian Anda memiliki metode lain yang mengembalikan angka pertama lebih kecil dari saya dalam daftar yang diberikan, atau saya jika tidak ada nomor lebih kecil:
public static int smaller(final List<Integer> ns, final int i) {
for (Integer n : ns)
if (n < i)
return n;
return i;
}
Metode-metode ini hampir identik. Menggunakan fungsi kelas-pertama tipe F, kita dapat menulis ulang ini menjadi satu metode sebagai berikut:
public static <T> T firstMatch(final List<T> ts, final F<T, Boolean> f, T z) {
for (T t : ts)
if (f.f(t))
return t;
return z;
}
Anda bisa menggunakan kelas anonim untuk menggunakan metode firstMatch:
F<Integer, Boolean> greaterThanTen = new F<Integer, Boolean> {
Boolean f(final Integer n) {
return n > 10;
}
};
int moreThanMyFingersCanCount = firstMatch(xs, greaterThanTen, x);
Ini adalah contoh yang benar-benar dibuat-buat, tetapi mudah untuk melihat bahwa dapat melewati fungsi seolah-olah mereka nilai adalah fitur yang sangat berguna. Lihat "Bisakah Bahasa Pemrograman Anda Melakukan Ini" oleh Joel sendiri.
Perpustakaan yang bagus untuk pemrograman Java dengan gaya ini: Java Fungsional.
Kelas dalam anonim digunakan dalam skenario berikut:
1.) Untuk Overriding (Sub classing), Ketika definisi kelas tidak dapat digunakan kecuali kasus saat ini:
class A{
public void methodA() {
System.out.println("methodA");
}
}
class B{
A a = new A() {
public void methodA() {
System.out.println("anonymous methodA");
}
};
}
2.) Untuk mengimplementasikan antarmuka, Ketika implementasi antarmuka hanya diperlukan untuk kasus saat ini:
interface interfaceA{
public void methodA();
}
class B{
interfaceA a = new interfaceA() {
public void methodA() {
System.out.println("anonymous methodA implementer");
}
};
}
3.) Argument Defined Anonymous inner class:
interface Foo {
void methodFoo();
}
class B{
void do(Foo f) { }
}
class A{
void methodA() {
B b = new B();
b.do(new Foo() {
public void methodFoo() {
System.out.println("methodFoo");
}
});
}
}
Saya menggunakannya kadang-kadang sebagai hack sintaks untuk Instantiation Map:
Map map = new HashMap() {{
put("key", "value");
}};
vs.
Map map = new HashMap();
map.put("key", "value");
Menghemat redundansi saat melakukan banyak pernyataan put. Namun, saya juga mengalami masalah dalam melakukan ini ketika kelas luar perlu diserialisasi melalui remoting.
Mereka biasanya digunakan sebagai bentuk panggilan balik verbal.
Saya kira Anda bisa mengatakan mereka lebih diuntungkan daripada tidak memilikinya, dan harus membuat kelas bernama setiap saat, tetapi konsep serupa diimplementasikan jauh lebih baik dalam bahasa lain (sebagai penutup atau blok)
Inilah contoh ayunan
myButton.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
// do stuff here...
}
});
Meskipun masih berantakan, itu jauh lebih baik daripada memaksa Anda untuk mendefinisikan kelas bernama untuk setiap pendengar membuang seperti ini (meskipun tergantung pada situasi dan penggunaan kembali, itu mungkin masih merupakan pendekatan yang lebih baik)
myButton.addActionListener(e -> { /* do stuff here */})
atau myButton.addActionListener(stuff)
akan terser.
Anda menggunakannya dalam situasi di mana Anda perlu membuat kelas untuk tujuan tertentu di dalam fungsi lain, misalnya, sebagai pendengar, sebagai runnable (untuk menelurkan utas), dll.
Idenya adalah bahwa Anda memanggil mereka dari dalam kode fungsi sehingga Anda tidak pernah merujuk mereka di tempat lain, sehingga Anda tidak perlu menyebutkannya. Kompilator hanya menyebutkannya.
Mereka pada dasarnya gula sintaksis, dan umumnya harus dipindahkan ke tempat lain ketika mereka tumbuh lebih besar.
Saya tidak yakin apakah itu salah satu kelebihan Java, meskipun jika Anda menggunakannya (dan kita semua sering menggunakannya, sayangnya), maka Anda bisa berpendapat bahwa itu adalah salah satunya.
GuideLines untuk Kelas Anonim.
Kelas anonim dideklarasikan dan diinisialisasi secara bersamaan.
Kelas anonim harus diperluas atau diterapkan ke satu dan hanya satu kelas atau antarmuka saja.
Karena kelas anonimouse tidak memiliki nama, kelas ini hanya dapat digunakan sekali.
misalnya:
button.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
}
});
ref.getClass().newInstance()
.
Ya, kelas batin anonim jelas merupakan salah satu kelebihan Jawa.
Dengan kelas batin anonim Anda memiliki akses ke variabel akhir dan anggota dari kelas sekitarnya, dan itu sangat berguna di pendengar dll.
Tetapi keuntungan utama adalah bahwa kode kelas dalam, yang (setidaknya harus) digabungkan erat dengan kelas / metode / blok di sekitarnya, memiliki konteks spesifik (kelas sekitarnya, metode, dan blok).
new Thread() {
public void run() {
try {
Thread.sleep(300);
} catch (InterruptedException e) {
System.out.println("Exception message: " + e.getMessage());
System.out.println("Exception cause: " + e.getCause());
}
}
}.start();
Ini juga salah satu contoh untuk tipe dalam anonim menggunakan utas
saya menggunakan objek anonim untuk memanggil Thread baru ..
new Thread(new Runnable() {
public void run() {
// you code
}
}).start();
Sebuah kelas batin dikaitkan dengan sebuah instance dari kelas luar dan ada dua jenis khusus: kelas lokal dan kelas Anonymous . Kelas anonim memungkinkan kita untuk mendeklarasikan dan membuat instance kelas pada saat yang sama, sehingga membuat kode ringkas. Kami menggunakannya ketika kami membutuhkan kelas lokal hanya sekali karena mereka tidak memiliki nama.
Pertimbangkan contoh dari doc di mana kita memiliki Person
kelas:
public class Person {
public enum Sex {
MALE, FEMALE
}
String name;
LocalDate birthday;
Sex gender;
String emailAddress;
public int getAge() {
// ...
}
public void printPerson() {
// ...
}
}
dan kami memiliki metode untuk mencetak anggota yang cocok dengan kriteria pencarian sebagai:
public static void printPersons(
List<Person> roster, CheckPerson tester) {
for (Person p : roster) {
if (tester.test(p)) {
p.printPerson();
}
}
}
di mana CheckPerson
antarmuka seperti:
interface CheckPerson {
boolean test(Person p);
}
Sekarang kita dapat menggunakan kelas anonim yang mengimplementasikan antarmuka ini untuk menentukan kriteria pencarian sebagai:
printPersons(
roster,
new CheckPerson() {
public boolean test(Person p) {
return p.getGender() == Person.Sex.MALE
&& p.getAge() >= 18
&& p.getAge() <= 25;
}
}
);
Di sini antarmuka sangat sederhana dan sintaksis kelas anonim tampaknya sulit dan tidak jelas.
Java 8 telah memperkenalkan istilah Fungsional Antarmuka yang merupakan antarmuka dengan hanya satu metode abstrak, maka kita dapat mengatakan CheckPerson
adalah antarmuka fungsional. Kita dapat menggunakan Ekspresi Lambda yang memungkinkan kita untuk melewatkan fungsi sebagai argumen metode sebagai:
printPersons(
roster,
(Person p) -> p.getGender() == Person.Sex.MALE
&& p.getAge() >= 18
&& p.getAge() <= 25
);
Kita dapat menggunakan antarmuka fungsional standar Predicate
sebagai pengganti antarmuka CheckPerson
, yang selanjutnya akan mengurangi jumlah kode yang diperlukan.
Kelas dalam anonim dapat bermanfaat sambil memberikan implementasi yang berbeda untuk objek yang berbeda. Tetapi harus digunakan sangat hemat karena menciptakan masalah untuk keterbacaan program.
Salah satu penggunaan utama dari kelas anonim dalam finalisasi kelas yang disebut finalizer wali . Di dunia Jawa menggunakan metode penyelesaian harus dihindari sampai Anda benar-benar membutuhkannya. Anda harus ingat, ketika Anda mengganti metode finalisasi untuk sub-kelas, Anda harus selalu memohon super.finalize()
juga, karena metode finalisasi kelas super tidak akan dipanggil secara otomatis dan Anda dapat mengalami masalah dengan kebocoran memori.
jadi mengingat fakta yang disebutkan di atas, Anda bisa menggunakan kelas anonim seperti:
public class HeavyClass{
private final Object finalizerGuardian = new Object() {
@Override
protected void finalize() throws Throwable{
//Finalize outer HeavyClass object
}
};
}
Dengan menggunakan teknik ini, Anda merasa lega dengan diri Anda dan pengembang lain untuk memanggil super.finalize()
setiap sub-kelas HeavyClass
yang membutuhkan metode penyelesaian.
Sepertinya tidak ada yang disebutkan di sini tetapi Anda juga dapat menggunakan kelas anonim untuk mengadakan argumen tipe umum (yang biasanya hilang karena penghapusan tipe) :
public abstract class TypeHolder<T> {
private final Type type;
public TypeReference() {
// you may do do additional sanity checks here
final Type superClass = getClass().getGenericSuperclass();
this.type = ((ParameterizedType) superClass).getActualTypeArguments()[0];
}
public final Type getType() {
return this.type;
}
}
Jika Anda akan membuat instance kelas ini dengan cara anonim
TypeHolder<List<String>, Map<Ineger, Long>> holder =
new TypeHolder<List<String>, Map<Ineger, Long>>() {};
lalu seperti itu holder
instance akan mengandung definisi tipe pass yang tidak dihapus.
Ini sangat berguna untuk membangun validator / deserializator. Anda juga dapat instantiate tipe generik dengan refleksi (jadi jika Anda ingin melakukan new T()
dalam tipe parametrized - Anda dipersilakan!) .
Cara terbaik untuk mengoptimalkan kode. juga, Kita bisa menggunakan metode kelas atau antarmuka utama.
import java.util.Scanner;
abstract class AnonymousInner {
abstract void sum();
}
class AnonymousInnerMain {
public static void main(String []k){
Scanner sn = new Scanner(System.in);
System.out.println("Enter two vlaues");
int a= Integer.parseInt(sn.nextLine());
int b= Integer.parseInt(sn.nextLine());
AnonymousInner ac = new AnonymousInner(){
void sum(){
int c= a+b;
System.out.println("Sum of two number is: "+c);
}
};
ac.sum();
}
}
Sebuah Anonymous batin Kelas digunakan untuk membuat sebuah objek yang tidak akan pernah dirujuk lagi. Tidak memiliki nama dan dideklarasikan dan dibuat dalam pernyataan yang sama. Ini digunakan di mana Anda biasanya menggunakan variabel objek. Anda mengganti variabel dengan new
kata kunci, panggilan ke konstruktor dan definisi kelas di dalam {
dan }
.
Saat menulis Program Berurutan di Jawa, biasanya akan terlihat seperti ini
ThreadClass task = new ThreadClass();
Thread runner = new Thread(task);
runner.start();
Yang ThreadClass
digunakan di sini akan ditentukan oleh pengguna. Kelas ini akan mengimplementasikan Runnable
antarmuka yang diperlukan untuk membuat utas. Dalam ThreadClass
satu run()
metode (hanya metode dalam Runnable
) perlu dilaksanakan juga. Jelas bahwa menyingkirkanThreadClass
akan lebih efisien dan itulah mengapa Kelas Batin Anonim ada.
Lihatlah kode berikut
Thread runner = new Thread(new Runnable() {
public void run() {
//Thread does it's work here
}
});
runner.start();
Kode ini menggantikan referensi yang dibuat task
pada contoh paling atas. Alih-alih memiliki kelas terpisah, Kelas Batin Anonim di dalam Thread()
konstruktor mengembalikan objek tanpa nama yang mengimplementasikan Runnable
antarmuka dan mengganti run()
metode. Metode ini run()
akan mencakup pernyataan di dalam yang melakukan pekerjaan yang diperlukan oleh utas.
Menjawab pertanyaan apakah Anonymous Inner Classes adalah salah satu kelebihan Java, saya harus mengatakan bahwa saya tidak begitu yakin karena saya tidak akrab dengan banyak bahasa pemrograman saat ini. Tapi yang bisa saya katakan adalah metode pengkodean yang lebih cepat dan mudah.
Referensi: Sams Teach Yourself Java dalam Edisi 21 Hari Ketujuh