ArrayList
содержит поле long
serialVersionUID
, чтобы помочь с сериализацией.Когда вы получаете значение, оно возвращает в штучной упаковке Long
.Вызов getDeclaredFields
on Long
возвращает массив, содержащий поле Long.MIN_VALUE
, которое является Long
.Отсюда и бесконечный цикл.
Чтобы разрешить его, я бы добавил специальную обработку для Long
, как вы делаете для Integer
.Вы также должны учитывать все другие примитивы в штучной упаковке, такие как Float
и Byte
.
Коллекции будут поддерживаться либо структурами, которые ссылаются друг на друга LinkedList
, либо массивами.Для связанных структур код будет проходить через них.Для поддержки собранных массивов необходимо определить, какие поля являются массивами, и выполнить итерации по ним.
Тип поля и получить его с помощью Field.getType .Массивы можно идентифицировать с помощью Class.isArray .Массивы для разных типов имеют разные типы, они не являются нереализованными, как дженерики Java.Массивы непримитивных значений могут быть преобразованы в Object[]
, что полезно в этом случае, но оно не является безопасным для типа .Чтобы получить тип объекта в массиве, можно использовать Class.getComponentType .
Чтобы выполнить рекурсивный анализ элементов массива, потребуется что-то вроде следующего.
final Class<?> fieldType = field.getType();
if (fieldType.isArray() && !fieldType.getComponentType().isPrimitive()) {
Object[] fs = (Object[]) f;
for (Object fi : fs) {
reflect(fi);
}
}
Другая проблема - циклические ссылки, которые могут вызвать дальнейшее StackOverflowException
.Если бы список был добавлен в качестве члена к себе, он будет повторяться бесконечно.Необходимо отслеживать ранее посещенный объект и не посещать их дважды.В идеале это будет использовать IdentityHashMap
, так как вы заботитесь о экземплярах объектов, а не об их равенстве.