ฉันพบวิธีรับสมาชิกที่สืบทอดผ่าน class.getDeclaredFields();
และเข้าถึงสมาชิกส่วนตัวผ่านclass.getFields()
แต่ฉันกำลังมองหาเขตข้อมูลที่สืบทอดแบบส่วนตัว ฉันจะบรรลุเป้าหมายนี้ได้อย่างไร?
ฉันพบวิธีรับสมาชิกที่สืบทอดผ่าน class.getDeclaredFields();
และเข้าถึงสมาชิกส่วนตัวผ่านclass.getFields()
แต่ฉันกำลังมองหาเขตข้อมูลที่สืบทอดแบบส่วนตัว ฉันจะบรรลุเป้าหมายนี้ได้อย่างไร?
คำตอบ:
สิ่งนี้ควรสาธิตวิธีแก้ปัญหา:
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));
}
}
(หรือClass.getDeclaredFields
สำหรับอาร์เรย์ของฟิลด์ทั้งหมด)
เอาท์พุต:
5
getSuperclass()
จนกว่าคุณจะไปถึงnull
ถ้าคุณต้องการไปให้สูง
getDeclaredFields()[0]
หรือgetDeclaredField("i")
แต่เป็นการ[0]
เข้าถึงอาร์เรย์ซ้ำในสองคำสั่งถัดไป
getDeclaredFields
มันก็เป็นเพียงการสาธิตวิธีการใช้ อัปเดตคำตอบแล้ว
แนวทางที่ดีที่สุดคือการใช้รูปแบบผู้เยี่ยมชมค้นหาฟิลด์ทั้งหมดในคลาสและซูเปอร์คลาสทั้งหมดและดำเนินการเรียกกลับ
Spring มีคลาสยูทิลิตี้ที่ดีReflectionUtils
ที่ทำเช่นนั้น: กำหนดวิธีการวนซ้ำในทุกฟิลด์ของคลาสซุปเปอร์ทั้งหมดด้วยการเรียกกลับ:ReflectionUtils.doWithFields()
เรียกใช้การเรียกกลับที่กำหนดบนฟิลด์ทั้งหมดในคลาสเป้าหมายขึ้นไปตามลำดับชั้นของคลาสเพื่อรับฟิลด์ที่ประกาศทั้งหมด
พารามิเตอร์:
- clazz - คลาสเป้าหมายที่จะวิเคราะห์
- fc - การเรียกกลับเพื่อเรียกใช้สำหรับแต่ละฟิลด์
- ff - ตัวกรองที่กำหนดฟิลด์ที่จะใช้การโทรกลับไป
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);
}
});
พบฟิลด์ไพรเวตบูลีนชั่วคราว javax.management.relation.RoleUnresolvedList.typeSafe ในคลาสประเภท javax.management.relation.RoleUnresolvedList
พบฟิลด์บูลีนชั่วคราวชั่วคราว javax.management.relation.RoleUnresolvedList.tainted ในประเภทคลาส javax.management.relation.Role
ฟิลด์FoundUnresolved ส่วนตัวชั่วคราว java.lang.Object [] java.util.ArrayList.elementData ในประเภทคลาส java.util.ArrayList
พบฟิลด์ private int java.util.ArrayList.size ในคลาสประเภท java.util.ArrayList
พบฟิลด์ป้องกันชั่วคราว int java util.AbstractList.modCount ในคลาสประเภท java.util.AbstractList
สิ่งนี้จะทำ:
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;
}
หากคุณใช้เครื่องมือครอบคลุมรหัสเช่นEclEmmaคุณต้องระวัง: พวกเขาเพิ่มฟิลด์ที่ซ่อนอยู่ในแต่ละชั้นเรียนของคุณ ในกรณีของ EclEmma ช่องเหล่านี้ถูกทำเครื่องหมายว่าสังเคราะห์และคุณสามารถกรองออกได้ดังนี้:
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);
}
(ตามคำตอบนี้ )
ในความเป็นจริงฉันใช้ hierachy ประเภทที่ซับซ้อนดังนั้นการแก้ปัญหาของคุณจึงไม่สมบูรณ์ ฉันต้องการโทรซ้ำเพื่อรับเขตข้อมูลส่วนตัวที่สืบทอดมาทั้งหมด นี่คือทางออกของฉัน
/**
* 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;
}
ฉันต้องการเพิ่มการสนับสนุนสำหรับฟิลด์ที่สืบทอดมาสำหรับพิมพ์เขียวใน รุ่นประชาชน ฉันได้รับวิธีนี้ซึ่งกระชับขึ้นเล็กน้อยสำหรับการดึงฟิลด์คลาส + ฟิลด์ที่สืบทอดมา
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);
}