Untuk mengakses bidang pribadi, Anda harus mendapatkannya dari bidang yang dideklarasikan kelas dan kemudian membuatnya dapat diakses:
Field f = obj.getClass().getDeclaredField("stuffIWant"); //NoSuchFieldException
f.setAccessible(true);
Hashtable iWantThis = (Hashtable) f.get(obj); //IllegalAccessException
EDIT : seperti yang telah berkomentar oleh aperkins , baik mengakses lapangan, pengaturan sebagai diakses dan mengambil nilai dapat membuang Exception
s, meskipun hanya diperiksa pengecualian Anda perlu berhati-hati dari yang berkomentar atas.
Itu NoSuchFieldException
akan dibuang jika Anda meminta bidang dengan nama yang tidak sesuai dengan bidang yang dinyatakan.
obj.getClass().getDeclaredField("misspelled"); //will throw NoSuchFieldException
The IllegalAccessException
akan dilemparkan jika lapangan tidak dapat diakses (misalnya, jika itu pribadi dan belum dilakukan diakses melalui hilang keluar f.setAccessible(true)
jalur.
The RuntimeException
s yang dapat dibuang yang baik SecurityException
s (jika JVM SecurityManager
tidak akan memungkinkan Anda untuk mengubah aksesibilitas lapangan), atau IllegalArgumentException
s, jika Anda mencoba dan akses lapangan pada objek bukan dari jenis kelas ladang ini:
f.get("BOB"); //will throw IllegalArgumentException, as String is of the wrong type
getDeclaredField()
tidak menemukan bidang jika didefinisikan dalam kelas induk - Anda juga harus beralih melalui hierarki kelas induk, memanggilgetDeclaredField()
masing-masing, hingga Anda menemukan kecocokan (setelah itu Anda dapat meneleponsetAccessible(true)
), atau Anda mencapaiObject
.private
bidang. Ini menghalangi akses tidak disengaja.Coba
FieldUtils
dari apache commons-lang3:sumber
Refleksi bukan satu-satunya cara untuk menyelesaikan masalah Anda (yaitu mengakses fungsionalitas / perilaku kelas / komponen)
Solusi alternatif adalah mengekstrak kelas dari .jar, mendekompilasinya menggunakan (katakanlah) Jode atau Jad , ganti bidang (atau tambahkan accessor), dan kompilasi ulang terhadap .jar yang asli. Kemudian letakkan .class yang baru di depan
.jar
dalam classpath, atau masukkan kembali di.jar
. (utilitas jar memungkinkan Anda untuk mengekstrak dan memasukkan kembali ke .jar yang ada)Seperti dicatat di bawah ini, ini menyelesaikan masalah yang lebih luas dalam mengakses / mengubah negara swasta daripada hanya mengakses / mengubah bidang.
Ini mengharuskan yang
.jar
tidak ditandatangani, tentu saja.sumber
Satu opsi lain yang belum disebutkan: gunakan Groovy . Groovy memungkinkan Anda untuk mengakses variabel instance pribadi sebagai efek samping dari desain bahasa. Apakah Anda memiliki pengambil untuk bidang tersebut, Anda bisa menggunakannya
sumber
Menggunakan Refleksi di Java Anda dapat mengakses semua
private/public
bidang dan metode dari satu kelas ke kelas lain. Tetapi sesuai dengan dokumentasi Oracle di bagian kelemahan yang mereka rekomendasikan:"Karena refleksi memungkinkan kode untuk melakukan operasi yang ilegal dalam kode non-reflektif, seperti mengakses bidang dan metode pribadi, penggunaan refleksi dapat menghasilkan efek samping yang tidak terduga, yang dapat membuat kode disfungsional dan dapat merusak portabilitas. Kode reflektif memecah abstraksi dan karenanya dapat mengubah perilaku dengan peningkatan platform "
di sini adalah mengikuti snap kode untuk menunjukkan konsep dasar Refleksi
Reflection1.java
Reflection2.java
Semoga ini bisa membantu.
sumber
Seperti yang disebutkan oxbow_lakes, Anda dapat menggunakan refleksi untuk mengatasi batasan akses (dengan asumsi SecurityManager Anda akan mengizinkan Anda).
Yang mengatakan, jika kelas ini dirancang dengan sangat buruk sehingga membuat Anda menggunakan peretasan seperti itu, mungkin Anda harus mencari alternatif. Tentu hack kecil ini mungkin menyelamatkan Anda beberapa jam sekarang, tetapi berapa biayanya di jalan?
sumber
Gunakan kerangka Soot Java Optimization untuk secara langsung memodifikasi bytecode. http://www.sable.mcgill.ca/soot/
Jelaga sepenuhnya ditulis dalam Java dan berfungsi dengan versi Java baru.
sumber
Anda perlu melakukan hal berikut:
sumber
Jika menggunakan Spring, ReflectionTestUtils menyediakan beberapa alat praktis yang membantu di sini dengan upaya minimal. Ini digambarkan sebagai "untuk digunakan dalam skenario pengujian unit dan integrasi" . Ada juga kelas serupa bernama ReflectionUtils tetapi ini digambarkan sebagai "Hanya untuk penggunaan internal" - lihat jawaban ini untuk interpretasi tentang apa artinya ini.
Untuk mengatasi contoh yang diposting:
sumber
ReflectionTestUtils
seperti dalam pengalaman saya, saya hanya perlu melakukan hal semacam ini dalam situasi pengujian.)Hanya catatan tambahan tentang refleksi: Saya telah mengamati dalam beberapa kasus khusus, ketika beberapa kelas dengan nama yang sama ada dalam paket yang berbeda, refleksi yang digunakan dalam jawaban atas mungkin gagal untuk mengambil kelas yang benar dari objek. Jadi jika Anda tahu apa itu package.class objek, maka lebih baik untuk mengakses nilai bidang privatnya sebagai berikut:
(Ini adalah contoh kelas yang tidak berfungsi untuk saya)
sumber
Anda dapat menggunakan @JailBreak Manifold untuk refleksi Java langsung dan aman:
@JailBreak
membukafoo
variabel lokal dalam kompiler untuk akses langsung ke semua anggota dalamFoo
hierarki.Demikian pula Anda dapat menggunakan metode ekstensi jailbreak () untuk sekali pakai:
Melalui
jailbreak()
metode ini Anda dapat mengakses anggota mana pun diFoo
hierarki.Dalam kedua kasus kompiler menyelesaikan akses bidang untuk Anda ketik-aman, seolah-olah bidang publik, sementara Manifold menghasilkan kode refleksi yang efisien untuk Anda di bawah tenda.
Temukan lebih lanjut tentang Manifold .
sumber
Sangat mudah dengan alat XrayInterface . Cukup tentukan getter / setter yang hilang, mis
dan xray proyek Anda yang dirancang buruk:
Secara internal ini bergantung pada refleksi.
sumber
Cobalah untuk mengatasi masalah untuk kasus ini, calass yang Anda ingin atur / dapatkan data adalah salah satu kelas Anda sendiri.
Cukup buat
public setter(Field f, Object value)
danpublic Object getter(Field f)
untuk itu. Anda bahkan dapat melakukan beberapa pemeriksaan keamanan pada fungsi anggota tesis Anda sendiri. Misalnya untuk setter:Tentu saja, sekarang Anda harus mencari tahu
java.lang.reflect.Field
untuksString
sebelum menetapkan nilai lapangan.Saya memang menggunakan teknik ini dalam ResultSet-to-dan-dari-model-mapper generik.
sumber