Saya menemukan cara untuk mendapatkan anggota yang diwariskan melalui class.getDeclaredFields();
dan akses ke anggota pribadi melalui class.getFields()
Tapi saya sedang mencari bidang warisan pribadi. Bagaimana saya bisa mencapai ini?
Saya menemukan cara untuk mendapatkan anggota yang diwariskan melalui class.getDeclaredFields();
dan akses ke anggota pribadi melalui class.getFields()
Tapi saya sedang mencari bidang warisan pribadi. Bagaimana saya bisa mencapai ini?
Jawaban:
Ini harus menunjukkan bagaimana menyelesaikannya:
import java.lang.reflect.Field;
class Super {
private int i = 5;
}
public class B extends Super {
public static void main(String[] args) throws Exception {
B b = new B();
Field f = b.getClass().getSuperclass().getDeclaredField("i");
f.setAccessible(true);
System.out.println(f.get(b));
}
}
(Atau Class.getDeclaredFields
untuk larik dari semua bidang.)
Keluaran:
5
getSuperclass()
sampai Anda mencapai null
jika Anda ingin naik lebih tinggi.
getDeclaredFields()[0]
atau getDeclaredField("i")
tetapi mengulang [0]
akses array dalam dua pernyataan berikutnya?
getDeclaredFields
. Jawaban telah diperbarui.
Pendekatan terbaik di sini adalah menggunakan Pola Pengunjung untuk menemukan semua bidang di kelas dan semua kelas super dan menjalankan tindakan panggilan balik padanya.
Spring memiliki kelas Utility yang bagus ReflectionUtils
yang melakukan hal itu: ia mendefinisikan metode untuk mengulang semua bidang dari semua kelas super dengan callback:ReflectionUtils.doWithFields()
Panggil callback yang diberikan pada semua bidang di kelas target, naikkan hierarki kelas untuk mendapatkan semua bidang yang dideklarasikan.
Parameter:
- clazz - kelas target yang akan dianalisis
- fc - callback yang akan dipanggil untuk setiap
kolom - ff - filter yang menentukan kolom untuk menerapkan callback
ReflectionUtils.doWithFields(RoleUnresolvedList.class,
new FieldCallback(){
@Override
public void doWith(final Field field) throws IllegalArgumentException,
IllegalAccessException{
System.out.println("Found field " + field + " in type "
+ field.getDeclaringClass());
}
},
new FieldFilter(){
@Override
public boolean matches(final Field field){
final int modifiers = field.getModifiers();
// no static fields please
return !Modifier.isStatic(modifiers);
}
});
Ditemukan bidang private transient boolean javax.management.relation.RoleUnresolvedList.typeSafe di kelas tipe javax.management.relation.RoleUnresolvedList
Ditemukan bidang private transient boolean javax.management.relation.RoleUnresolvedList.tainted di
bidang kelas jenis javax.management.relation private transient java.lang.Object [] java.util.ArrayList.elementData dalam jenis kelas java.util.ArrayList
Ditemukan bidang private int java.util.ArrayList.size di kelas jenis java.util.ArrayList
Ditemukan bidang dilindungi sementara int java. util.AbstractList.modCount dalam kelas tipe java.util.AbstractList
Ini akan melakukannya:
private List<Field> getInheritedPrivateFields(Class<?> type) {
List<Field> result = new ArrayList<Field>();
Class<?> i = type;
while (i != null && i != Object.class) {
Collections.addAll(result, i.getDeclaredFields());
i = i.getSuperclass();
}
return result;
}
Jika Anda menggunakan alat cakupan kode seperti EclEmma , Anda harus berhati-hati: mereka menambahkan bidang tersembunyi ke setiap kelas Anda. Untuk EclEmma, bidang ini ditandai sintetis , dan Anda dapat memfilternya seperti ini:
private List<Field> getInheritedPrivateFields(Class<?> type) {
List<Field> result = new ArrayList<Field>();
Class<?> i = type;
while (i != null && i != Object.class) {
for (Field field : i.getDeclaredFields()) {
if (!field.isSynthetic()) {
result.add(field);
}
}
i = i.getSuperclass();
}
return result;
}
public static Field getField(Class<?> clazz, String fieldName) {
Class<?> tmpClass = clazz;
do {
try {
Field f = tmpClass.getDeclaredField(fieldName);
return f;
} catch (NoSuchFieldException e) {
tmpClass = tmpClass.getSuperclass();
}
} while (tmpClass != null);
throw new RuntimeException("Field '" + fieldName
+ "' not found on class " + clazz);
}
(berdasarkan jawaban ini )
Sebenarnya saya menggunakan hierachy tipe kompleks sehingga solusi Anda tidak lengkap. Saya perlu melakukan panggilan rekursif untuk mendapatkan semua bidang warisan pribadi. Inilah solusi saya
/**
* Return the set of fields declared at all level of class hierachy
*/
public Vector<Field> getAllFields(Class clazz) {
return getAllFieldsRec(clazz, new Vector<Field>());
}
private Vector<Field> getAllFieldsRec(Class clazz, Vector<Field> vector) {
Class superClazz = clazz.getSuperclass();
if(superClazz != null){
getAllFieldsRec(superClazz, vector);
}
vector.addAll(toVector(clazz.getDeclaredFields()));
return vector;
}
Saya perlu menambahkan dukungan untuk bidang warisan untuk cetak biru di Model Citizen . Saya mendapatkan metode ini yang sedikit lebih ringkas untuk mengambil bidang Kelas + bidang yang diwariskan.
private List<Field> getAllFields(Class clazz) {
List<Field> fields = new ArrayList<Field>();
fields.addAll(Arrays.asList(clazz.getDeclaredFields()));
Class superClazz = clazz.getSuperclass();
if(superClazz != null){
fields.addAll(getAllFields(superClazz));
}
return fields;
}
private static Field getField(Class<?> clazz, String fieldName) {
Class<?> tmpClass = clazz;
do {
for ( Field field : tmpClass.getDeclaredFields() ) {
String candidateName = field.getName();
if ( ! candidateName.equals(fieldName) ) {
continue;
}
field.setAccessible(true);
return field;
}
tmpClass = tmpClass.getSuperclass();
} while ( clazz != null );
throw new RuntimeException("Field '" + fieldName +
"' not found on class " + clazz);
}