Java 使用泛型获取所有字段
任务: 您需要从所有超类获取指定类的所有字段,包括private和inluding字段。 通常的方法是循环获取字段:Java 使用泛型获取所有字段,java,generics,Java,Generics,任务: 您需要从所有超类获取指定类的所有字段,包括private和inluding字段。 通常的方法是循环获取字段: private static void getAllFieldsRecursive(List<Field> fields, Class<?> type) { fields.addAll(Arrays.asList(type.getDeclaredFields())); if (type.getSuperclass() != null)
private static void getAllFieldsRecursive(List<Field> fields, Class<?> type) {
fields.addAll(Arrays.asList(type.getDeclaredFields()));
if (type.getSuperclass() != null) {
getAllFieldsRecursive(fields, type.getSuperclass());
}
}
将给出以下结果:
字符串B.myfield;字符串B.otherBField;字符串A.myfield,字符串A.otherField
使用Set不会有帮助,因为字符串A.myfield不等于B.myfield
下面的解决方案/**
/**
* Collect all fields declared, including superclasses.
* @param type class
* @return
*/
public static List<Field> getAllFields(Class<?> type) {
List<Field> fields = new ArrayList<>();
getAllFieldsRecursive(fields, type);
return fields;
}
/**
* Get fields recursively, starting from child.
* Starting from child is important to support fields overriding.
* @param fields all fields collected
* @param type currently scanned class
* Example:
* class A {String myfield; String otherField}
* class B extends class A {String myField; String bField}
* Result: String B.myfield; String B.bField; String A.otherField
*/
private static void getAllFieldsRecursive(List<Field> fields, Class<?> type) {
List<Field> declaredFields = Arrays.asList(type.getDeclaredFields()); //Start from child
for (Field declaredField : declaredFields){
if (!genericContainsField(declaredField, fields))
fields.add(declaredField); //if field is not overridden in child, add it
}
if (type.getSuperclass() != null) {
getAllFieldsRecursive(fields, type.getSuperclass());
}
}
/**
*
* @param declaredField field we are comparing
* @param fields current fields list
* @return
*/
private static boolean genericContainsField(Field declaredField, List<Field> fields){
for (Field field:fields){
if (genericEqualsFields(field, declaredField))
return true;
}
return false;
}
/**
* Compares this {@code Field} against the specified object. Returns
* true if the objects are the same. Two {@code Field} objects are the same if
* they were have the same name and type.
* Declared by the same class is NOT needed
* Hack for Generic lookup, based on Field.equals()
*/
private static boolean genericEqualsFields(Field obj, Field other) {
return (obj.getName() == other.getName())
&& (obj.getType() == other.getType());
}
*收集所有声明的字段,包括超类。
*@param类型类
*@返回
*/
公共静态列表getAllFields(类类型){
列表字段=新的ArrayList();
getAllFieldsRecursive(字段,类型);
返回字段;
}
/**
*从子级开始递归获取字段。
*从子级开始对于支持字段重写很重要。
*@param fields收集的所有字段
*@param-type当前扫描的类
*例如:
*类{String myfield;String otherField}
*类B扩展类A{String myField;String bField}
*结果:字符串B.myfield;字符串B.B字段;字符串A.otherField
*/
私有静态void getAllFieldsRecursive(列表字段,类类型){
List declaredFields=Arrays.asList(type.getDeclaredFields());//从子级开始
for(字段declaredField:declaredFields){
如果(!genericContainsField(declaredField,fields))
fields.add(declaredField);//如果字段在子级中未被重写,则添加它
}
if(type.getSuperclass()!=null){
getAllFieldsRecursive(字段,类型.getSuperclass());
}
}
/**
*
*@param declaredField我们正在比较
*@param字段当前字段列表
*@返回
*/
私有静态布尔genericContainsField(字段declaredField,列表字段){
用于(字段:字段){
if(一般质量字段(字段、申报字段))
返回true;
}
返回false;
}
/**
*将此{@code Field}与指定的对象进行比较。退换商品
*如果对象相同,则为true。两个{@code Field}对象是相同的,如果
*它们的名称和类型相同。
*不需要由同一类声明
*基于Field.equals()的通用查找的Hack
*/
私有静态布尔genericEqualsFields(字段obj、字段other){
返回值(obj.getName()==other.getName())
&&(obj.getType()==其他.getType());
}
“但是,本案例不包括覆盖字段。”没有覆盖字段。在那里显示四个字段是完全正确的。B
的实例有四个独立的字段。还不清楚这与泛型有什么关系…@Jon Skeet,不,显示所有4个字段并不总是正确的。例如,在某些情况下,您只需要知道字段的最新版本及其支持的注释。是的,字段是隐藏的,而不是被覆盖的。没有“最后版本”这样的东西。您的问题是:“您需要获取指定类的所有字段,包括来自所有超类的private和inluding字段。”在您给出的示例中,有四个这样的字段。如果你确实有不同的任务,你应该在问题中陈述。在描述的任务中显示所有4个字段总是正确的。
/**
* Collect all fields declared, including superclasses.
* @param type class
* @return
*/
public static List<Field> getAllFields(Class<?> type) {
List<Field> fields = new ArrayList<>();
getAllFieldsRecursive(fields, type);
return fields;
}
/**
* Get fields recursively, starting from child.
* Starting from child is important to support fields overriding.
* @param fields all fields collected
* @param type currently scanned class
* Example:
* class A {String myfield; String otherField}
* class B extends class A {String myField; String bField}
* Result: String B.myfield; String B.bField; String A.otherField
*/
private static void getAllFieldsRecursive(List<Field> fields, Class<?> type) {
List<Field> declaredFields = Arrays.asList(type.getDeclaredFields()); //Start from child
for (Field declaredField : declaredFields){
if (!genericContainsField(declaredField, fields))
fields.add(declaredField); //if field is not overridden in child, add it
}
if (type.getSuperclass() != null) {
getAllFieldsRecursive(fields, type.getSuperclass());
}
}
/**
*
* @param declaredField field we are comparing
* @param fields current fields list
* @return
*/
private static boolean genericContainsField(Field declaredField, List<Field> fields){
for (Field field:fields){
if (genericEqualsFields(field, declaredField))
return true;
}
return false;
}
/**
* Compares this {@code Field} against the specified object. Returns
* true if the objects are the same. Two {@code Field} objects are the same if
* they were have the same name and type.
* Declared by the same class is NOT needed
* Hack for Generic lookup, based on Field.equals()
*/
private static boolean genericEqualsFields(Field obj, Field other) {
return (obj.getName() == other.getName())
&& (obj.getType() == other.getType());
}