Saya baru ke Jawa; melalui studi saya, saya membaca bahwa refleksi digunakan untuk memanggil kelas dan metode, dan untuk mengetahui metode mana yang diterapkan atau tidak.
Kapan saya harus menggunakan refleksi, dan apa perbedaan antara menggunakan refleksi dan instantiating objek dan memanggil metode dengan cara tradisional?
java
reflection
Hamzah khammash
sumber
sumber
Jawaban:
Refleksi jauh lebih lambat daripada hanya memanggil metode dengan nama mereka, karena harus memeriksa metadata dalam bytecode daripada hanya menggunakan alamat dan konstanta yang telah dikompilasi sebelumnya.
Refleksi juga lebih kuat: Anda dapat mengambil definisi dari
protected
ataufinal
anggota, menghapus perlindungan dan memanipulasi seolah-olah telah dinyatakan bisa berubah! Jelas ini merongrong banyak jaminan bahasa yang biasanya dibuat untuk program Anda dan bisa sangat, sangat berbahaya.Dan ini cukup banyak menjelaskan kapan menggunakannya. Biasanya, jangan. Jika Anda ingin memanggil metode, panggil saja. Jika Anda ingin bermutasi anggota, hanya menyatakan itu bisa berubah daripada pergi di belakang kompilasi.
Salah satu penggunaan refleksi dunia nyata yang berguna adalah ketika menulis sebuah kerangka kerja yang harus beroperasi dengan kelas-kelas yang ditentukan pengguna, di mana penulis kerangka kerja tidak tahu apa yang akan menjadi anggota (atau bahkan kelas) akan. Refleksi memungkinkan mereka untuk berurusan dengan kelas apa pun tanpa menyadarinya terlebih dahulu. Sebagai contoh, saya rasa tidak mungkin untuk menulis perpustakaan berorientasi aspek yang kompleks tanpa refleksi.
Sebagai contoh lain, JUnit digunakan untuk menggunakan sedikit refleksi sepele: ia menyebutkan semua metode di kelas Anda, mengasumsikan bahwa semua yang dipanggil
testXXX
adalah metode pengujian, dan mengeksekusi hanya itu. Tapi sekarang ini bisa dilakukan lebih baik dengan anotasi, dan pada kenyataannya JUnit 4 sebagian besar telah pindah ke anotasi.sumber
Saya pernah seperti Anda dulu, saya tidak tahu banyak tentang refleksi - masih belum - tetapi saya pernah menggunakannya sekali.
Saya memiliki kelas dengan dua kelas batin, dan setiap kelas memiliki banyak metode.
Saya perlu memohon semua metode di kelas batin, dan memakainya secara manual akan terlalu banyak pekerjaan.
Menggunakan refleksi, saya bisa memanggil semua metode ini hanya dalam 2-3 baris kode, bukan jumlah metode itu sendiri.
sumber
Saya akan mengelompokkan penggunaan refleksi ke dalam tiga kelompok:
sumber
Refleksi memungkinkan suatu program bekerja dengan kode yang mungkin tidak ada dan melakukannya dengan cara yang andal.
"Kode normal" memiliki snippet seperti
URLConnection c = null
yang dengan kehadirannya semata-mata menyebabkan pemuat kelas memuat kelas URLConnection sebagai bagian dari memuat kelas ini, melempar pengecualian dan keluar dari ClassNotFound.Refleksi memungkinkan Anda memuat kelas berdasarkan namanya dalam bentuk string dan mengujinya untuk berbagai properti (berguna untuk beberapa versi di luar kendali Anda) sebelum meluncurkan kelas aktual yang bergantung padanya. Contoh khas adalah kode khusus OS X yang digunakan untuk membuat program Java terlihat asli di bawah OS X, yang tidak ada pada platform lain.
sumber
Pada dasarnya, refleksi berarti menggunakan kode program Anda sebagai data.
Oleh karena itu, menggunakan refleksi mungkin merupakan ide yang baik ketika kode program Anda merupakan sumber data yang berguna. (Tapi ada kompromi, jadi itu mungkin bukan ide yang bagus.)
Sebagai contoh, pertimbangkan kelas sederhana:
dan Anda ingin menghasilkan XML darinya. Anda dapat menulis kode untuk menghasilkan XML:
Tapi ini banyak kode boilerplate, dan setiap kali Anda mengubah kelas, Anda harus memperbarui kode. Sungguh, Anda bisa menggambarkan seperti apa kode ini
Ini adalah suatu algoritma, dan input algoritma adalah kelas: kita perlu namanya, dan nama, tipe dan nilai propertinya. Di sinilah refleksi masuk: itu memberi Anda akses ke informasi ini. Java memungkinkan Anda untuk memeriksa tipe menggunakan metode
Class
kelas.Beberapa kasus penggunaan lainnya:
Namun, refleksi penuh berarti tidak hanya melihat kode yang ada (yang dengan sendirinya dikenal sebagai "introspeksi"), tetapi juga memodifikasi atau menghasilkan kode. Ada dua kasus penggunaan yang menonjol di Jawa untuk ini: proksi dan ejekan.
Katakanlah Anda memiliki antarmuka:
dan Anda memiliki implementasi yang melakukan sesuatu yang menarik:
Dan sebenarnya Anda juga memiliki implementasi kedua:
Sekarang Anda juga ingin beberapa keluaran log; Anda hanya ingin pesan log setiap kali suatu metode dipanggil. Anda dapat menambahkan output log ke setiap metode secara eksplisit, tetapi itu akan mengganggu, dan Anda harus melakukannya dua kali; satu kali untuk setiap implementasi. (Bahkan lebih ketika Anda menambahkan lebih banyak implementasi.)
Sebagai gantinya, Anda dapat menulis proxy:
Namun, sekali lagi, ada pola berulang yang dapat dijelaskan oleh suatu algoritma:
dan input dari algoritma ini adalah definisi antarmuka.
Refleksi memungkinkan Anda untuk menentukan kelas baru menggunakan algoritma ini. Java memungkinkan Anda melakukan ini menggunakan metode
java.lang.reflect.Proxy
kelas, dan ada perpustakaan yang memberi Anda lebih banyak kekuatan.Jadi apa saja kelemahan refleksi?
sumber
Refleksi dapat secara otomatis menjaga bagian-bagian program Anda dalam sinkronisasi, di mana sebelumnya, Anda harus memperbarui program secara manual untuk menggunakan antarmuka baru.
sumber