RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1033131
Accepted
skyho
skyho
Asked:2020-10-10 15:58:58 +0000 UTC2020-10-10 15:58:58 +0000 UTC 2020-10-10 15:58:58 +0000 UTC

如何使用反射绕过一个实体分多个类的所有字段,即祖先类中的字段

  • 772

我有一个实体分为几个类

public abstract class OneBaseAbstract {

    private Long id;

    private String name;

    public OneBaseAbstract() {
    }

...

}

第二

public abstract class TwoBaseAbstract extends OneBaseAbstract{

    private Integer num;

    private String mark;

    public TwoBaseAbstract() {
        super();
    }
...
}

第三

public class Produce extends TwoBaseAbstract {

    private String name2;

    private String product;

    public Produce() {
        super();
    }
...
}

实体中有几十个字段,很多表,为了测试手动填写,可能会耗费大量时间和大量错误。我有自动对象创建,但这仅适用于没有祖先的类。

这是一个解析对象的类,用任意数据填充它。

/**класс утилит для заполнения значений поля объекта*/
public final class FieldProcessForFillUtils {

    private static final Logger LOGGER = LoggerFactory.getLogger(FieldProcessForFillUtils.class);
    private static final String LOGGER_MESSAGE_DATA_TYPE = "The data type is not defined here.";

    /**
     *  Заполнение полей объекта.
     * @param object - обрабатываемый объект, любого типа данных
     * @param values - коллекция значений, которые будут сгенерированы для полей обрабатываемого объекта
     * @param <S> - универсальный параметр, указывает на тип данных передаваемого объекта
     * @return  - возвращает обработанный объект. S - универсальный параметр, хранит информацию об текущем
     *            обрабатываемом объекте
     */
    public static  <S> S fillData (S object, List<Object> values){

        return obtainMetadataOfObject(object, values);
    }


    /**
     * Извлечение метаданных из полученного объекта, для дальнейшей обработки
     * @param object - обрабатываемый объект
     * @param values - коллекция значений, которые будут сгенерированы для полей обрабатываемого объекта
     * @param <S> - универсальный параметр, указывает на тип данных передаваемого объекта
     * @return - возвращает обработанный объект. S - универсальный параметр, хранит информацию об текущем
     * обрабатываемом объекте
     */
    private static <S> S obtainMetadataOfObject(S object, List<Object> values){

        Class<?> objectClass = object.getClass();
        Field[] fields = objectClass.getDeclaredFields();

        parseArrFields(fields, object, values);

        return object;
    }

    /**парсинг массива полей*/
    private static void parseArrFields(Field [] fields, Object object, List<Object> values){

        for(Field field : fields){
            Class<?> type = field.getType();
            String typeName = type.getSimpleName();

            setValue(field, typeName, object, values);
        }

    }

    /**
     *
     * @param field - поле для изменения
     * @param typeName - имя типа данных текущего поля
     * @param object - объект, поле которого обрабатываются на текущий момент
     * @param values - коллекция , куда будут заносится сгенерированные значения,
     *               которые будут установлены  в обрабатываемые поля текущего объекта
     */
    private static void setValue(Field field, String typeName, Object object, List<Object> values){

        Integer yearMin = 2017;
        Integer yearMax = 2019;

        Long minLimitForRandom = 1L;
        Long maxLimitForRandom = 200000L;

        switch (typeName){

            case "Long" : /* тип данных*/
                field.setAccessible(true);
                try {
                    Double aDouble = randomNumberGenerator(maxLimitForRandom , minLimitForRandom);
                    Long id = aDouble.longValue();

                    field.set(object, id);
                    values.add(id);

                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }

                break;

            case "Integer":
                field.setAccessible(true);
                try {

                    Integer number = randomNumberGenerator(maxLimitForRandom, minLimitForRandom).intValue();
                    field.set(object, number);
                    values.add(number);

                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
                break;

            case "String":
                field.setAccessible(true);
                try {
                    String randomStr = generatingRandomStringAlphabetic();
                    field.set(object, randomStr);
                    values.add(randomStr);

                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
                break;

            case "LocalDate":


                field.setAccessible(true);
                LocalDate localDate = generatorLocalDate(yearMin, yearMax);
                try {
                    field.set(object, localDate);
                    values.add(localDate);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
                break;

            case "LocalDateTime":

                field.setAccessible(true);

                LocalDateTime localDateTime = generatorLocalDateTime(yearMin, yearMax);

                try {
                    field.set(object, localDateTime);
                    values.add(localDateTime);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
                break;

            case "Character":
                field.setAccessible(true);
                Character character = generateRandomSpecialCharacters();

                try {
                    field.set(object, character);
                    values.add(character);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
                break;

            default:
                LOGGER.error(LOGGER_MESSAGE_DATA_TYPE);

        }

    }

}

这段代码,当它遇到一个分为几个类的对象时,只能看到后代类的字段。

可以在代码中更正什么,以便Field[] 字段数组

 Field[] fields = objectClass.getDeclaredFields();

得到所有字段,包括祖先类的字段

如此决定

 private static <S> void obtainMetadataOfObject(S object, List<Object> values) {

    Class<?> objectClass = object.getClass();

    Field[] fields;

    Class superClazz = objectClass.getSuperclass();

    String nameObjectClass = "Object";

    String simpleNameObjectExpected = superClazz.getSimpleName();

    boolean isObjectClass = Objects.equals(simpleNameObjectExpected, nameObjectClass);


    if(!isObjectClass){

        List<Field> allFields = getAllFields(objectClass);
        fields = convertCollectionToArray(allFields);
    } else {
        fields = objectClass.getDeclaredFields();
    }

    compareLengthArrays(fields.length, values.size());

    parseArrFields(fields, object, values);

}


/**
 * Обработка полей составного класса, используется рефлексия
 * @param clazz - тип объекта
 * @return - возвращает список полей составного класса
 */
private static List<Field> getAllFields(Class clazz) {

    List<Field> fields = Arrays.asList(clazz.getDeclaredFields());

    List<Field> fieldList = new ArrayList<>(fields);

    Class superClazz = clazz.getSuperclass();
    if(superClazz != null){

        fieldList.addAll(getAllFields(superClazz));
    }


    return fieldList ;
}

/** Преобразование коллекции в массив
 * Field[]::new - указывает на то, что каждый элемент коллекции нужно
 * передать в конструктор класса Field и после создания экземпляра, данный экземпляр
 * добавляется в указанный тип массива*/
private static Field[] convertCollectionToArray(List<Field> fields){

    Stream<Field> fieldStream = fields.stream();

    return fieldStream.toArray(Field[]::new);

}
java
  • 1 1 个回答
  • 10 Views

1 个回答

  • Voted
  1. Best Answer
    Sergey Mitrofanov
    2020-10-10T18:16:54Z2020-10-10T18:16:54Z

    递归遍历objectClass.getSuperclass()

        public static Field[] getAllFields(Object o){
            System.out.println("Get all fields from Object");
            Class<?> c = o.getClass();
            Field[] fields = {};
            while (c!=null){
                fields = ArrayUtils.addAll(fields, c.getDeclaredFields());
                c = c.getSuperclass();
            }
            return fields;
        }
    

    阵列粘合不是最佳的;)

    • 2

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    根据浏览器窗口的大小调整背景图案的大小

    • 2 个回答
  • Marko Smith

    理解for循环的执行逻辑

    • 1 个回答
  • Marko Smith

    复制动态数组时出错(C++)

    • 1 个回答
  • Marko Smith

    Or and If,elif,else 构造[重复]

    • 1 个回答
  • Marko Smith

    如何构建支持 x64 的 APK

    • 1 个回答
  • Marko Smith

    如何使按钮的输入宽度?

    • 2 个回答
  • Marko Smith

    如何显示对象变量的名称?

    • 3 个回答
  • Marko Smith

    如何循环一个函数?

    • 1 个回答
  • Marko Smith

    LOWORD 宏有什么作用?

    • 2 个回答
  • Marko Smith

    从字符串的开头删除直到并包括一个字符

    • 2 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5