#java
#java
Вопрос:
Предположим, у вас есть объект Java, можно ли определить, где он существует circular references inside that java object
?
Я хотел бы услышать, существует ли библиотека для решения этой проблемы.
Заранее спасибо.
Ответ №1:
Будьте осторожны, это нетривиальная задача, но вы уже знаете это, верно? 😉
В Java существует реализация IdentityHashMap, которая предназначена для использования в таких случаях.
Ответ №2:
Концептуально простой, но может быть довольно сложным в реализации.
Во-первых, многое зависит от того, с каким типом объектов вы имеете дело. Если существует только небольшое количество классов объектов, и вы «владеете» классами и можете изменять их, добавляя код «поиска самостоятельно», тогда это становится намного проще:
Добавьте интерфейс к каждому классу и реализуйте метод «search yourself» в каждом классе. Метод получает список объектов и возвращает код возврата. Метод сравнивает свой собственный адрес с каждым объектом в списке, возвращая true (т. Е. Цикл найден), если один из них совпадает. Затем (если совпадений нет) он добавляет свой собственный адрес в список и вызывает, в свою очередь, метод «search yourself» для каждой ссылки на объект, которую он содержит. Если какой-либо из этих вызовов приводит к коду возврата true, который возвращается, в противном случае возвращается false. (Это «рекурсивный поиск в глубину».)
Если вы не «владеете» классами, то вы должны использовать отражения для реализации по существу вышеупомянутого алгоритма без изменения классов.
Существуют другие алгоритмы поиска, которые можно использовать — «сначала вширь» и различные нерекурсивные версии «сначала в глубину», но все они представляют собой компромиссы того или иного рода между хранилищем кучи, хранилищем стека и производительностью.
Комментарии:
1. (IdentityHashMap был бы хорошим способом реализовать список объектов.)
2. Можно также заменить список объектов битовой маской, при этом позиция данного объекта в маске присваивается (с использованием глобального счетчика) при первом поиске объекта.
3. Конечно, вы, вероятно, можете наилучшим образом реализовать алгоритм, добавив поля к объектам. Для каждого объекта требуется bool, два целых числа и указатель на объект вашего интерфейса «поиск самостоятельно». Рекурсия не требуется, и нет опасности переполнения стека. Будет выполняться менее чем за время bM, где N — общее количество объектов, а M — общее количество указателей между объектами.
Ответ №3:
Немного боковой ответ, но как насчет использования, net.sf.json.JSONObject.fromObject(...)
которое проверяет циклические ссылки и выдает исключение, если таковые обнаружены. Кроме того, вы можете настроить библиотеку для обработки циклических ссылок по-другому, если это необходимо. Вам пришлось бы написать средство получения для тех членов класса, которые существуют в циклических отношениях, поскольку именно это JSONObject использует для создания JSON.
Комментарии:
1. Спасибо. даже я только что попробовал использовать XStream json, я получил это: com.thoughtworks.xstream.core. TreeMarshaller$ CircularReferenceException: но тогда я не знаю, где это циклическая ссылка. Есть идеи?
2. Для этой json-библиотеки вы можете зарегистрировать CycleDetectionStrategy и получить доступ к «повторяющемуся» объекту. Возможно, было бы возможно сделать что-то подобное с XStream, но по какой-то причине XStream API у меня в данный момент не работает, поэтому я не могу проверить!
3. Спасибо. есть идеи, если бы я только что попробовал: JSONObject JSONObject = JSONObject.fromObject(MyModel ); и я получил это исключение: Исключение в потоке «main» java.lang. Ошибка NoClassDefFoundError: org/apache/commons/lang/exception/NestableRuntimeException Спасибо!
4. Нет, я понял это: net / sf /ezmorph /Morpher
5. Вам не хватает зависимостей библиотеки, которые задокументированы на главной странице .
Ответ №4:
Это кажется простой задачей для программирования. Используйте Java Reflection API для обхода графика объектов Java и сбора посещенных объектов. Если вы посещаете объект, который уже находится в наборе, это означает, что должен быть контур. Для обхода используйте алгоритмы BFS или DFS.
Ответ №5:
Вам не нужна никакая библиотека. Это простой алгоритм поиска по ширине и API отражения. Конечно, вы можете попытаться найти библиотеку, реализующую этот алгоритм.