Автоматический указатель Swizzling от Java? - PullRequest
1 голос
/ 29 февраля 2012

Предположим, у нас есть произвольный граф, представленный узлами и указателями, подобными этому:

class Node
{
    public ValueType data;
    public ArrayList<Node> adj;
}

Теперь я хочу взять его копию или записать / прочитать на диске (AKA сериализует / десериализует). Я также знаю, что это можно сделать с помощью алгоритма поиска + ассоциативных массивов. И, оказывается, этот метод называется swizzling .

Вот мой вопрос:

Я слышал, что в Java, объявив класс как Serializable, эта функция предоставляется вам автоматически. (для меня это звучит как волшебство!)

Правильно ли это утверждение? Запускает ли Java автоматически BFS для обхода графа и перемещения указателей? Другими словами, сериализует / десериализует ли клон объект для меня? (совершенно новый объект с той же структурой, но с новыми узлами и обновленными указателями)

Если да, то что, если в некоторых случаях я просто хочу скопировать указатели? что если я захочу сериализовать объект, чтобы сохранить исходные указатели?

Я ценю любые комментарии по этому поводу. : -)

Ответы [ 2 ]

1 голос
/ 29 февраля 2012

Сначала я отвечу на ваш последний вопрос.Целью сериализации не является клонирование графа объектов в памяти.Он предназначен для преобразования графа объекта в поток байтов, чтобы выполнять такие вещи, как сохранение в файле или отправка по сети.Процесс десериализации может быть выполнен на другом компьютере, в другое время, в другом процессе или даже не-Java-программой, поэтому не стоит ожидать ссылки на те же объекты, что и раньше.Это структура и содержимое графа объектов, которые сохраняются и впоследствии восстанавливаются, а не адреса в памяти.Именно по этой причине не имеет смысла сериализовать все объекты.Например, сериализация Thread не будет полезной, поскольку она не будет иметь смысла вне текущего экземпляра программы.

Магия автоматической сериализации не очень сложна.Игнорирование пользовательских методов сериализации, которые вы можете написать для своих собственных классов, чтобы точно контролировать поведение сериализации и десериализации, да, система будет эффективно проходить по графу объектов, чтобы генерировать поток байтов.Этот обход обычно делается как DFS, а не BFS.По сути, вы просите Java сериализовать объект, передавая ссылку на него.Эта ссылка будет служить корнем графа объекта.Оттуда Java рекурсивно сериализует поля этого объекта.Конечно, он отслеживает циклические ссылки и записывает соответствующие маркировки в выходной поток, так что десериализатор может подключать указатели и воссоздавать структуру, как это было раньше.

1 голос
/ 29 февраля 2012

Не думаю, что вы думаете об этом, но в значительной степени. Сериализация в Java - довольно непрозрачный процесс. Все, что вам действительно нужно знать о нем, это предположить, что класс и все типы его членов реализуют Serializable, Java знает, как преобразовать его в поток байтов и как воссоздать экземпляры объектов из этого поток, когда вы просите его десериализовать.

Исходя из C ++, сначала это казалось черной магией. Я скептически относился ко всему процессу и не очень доверял JVM, чтобы позаботиться об этом за меня, потому что в C ++ он просто не знает достаточно о простом объекте, чтобы сделать это. Но на самом деле это очень хорошо, если вам нужен только доступ к данным из Java.

По сути, нет необходимости беспокоиться о указателях или о том, какой алгоритм он использует ниже. Вы просто указываете ему написать объект, а затем позже говорите ему прочитать его обратно, и вы по сути получите ту же структуру в памяти, что и раньше.

Еще одна вещь: если вы объявите переменную как transient, она не будет сохранена, и вам придется восстанавливать ее самостоятельно. Это полезно, если у вас есть поля, которые кэшируют определенные значения, для которых вы не хотите тратить пространство, или поля с конфиденциальными данными, которые вы не хотите лежать. Но вам придется помнить, чтобы восстановить его самостоятельно.

...