Я читал источник Java ArrayList, и я наткнулся на его объявление массива:
private transient Object[] elementData;
Почему это должно быть временным? Почему этот класс не может быть сериализован?
Спасибо за помощь!
Я читал источник Java ArrayList, и я наткнулся на его объявление массива:
private transient Object[] elementData;
Почему это должно быть временным? Почему этот класс не может быть сериализован?
Спасибо за помощь!
Он может быть сериализован; класс ArrayList
просто заботится о себе, а не использует механизм по умолчанию. Посмотрите на методы writeObject()
и readObject()
в этом классе, которые являются частью стандартного механизма сериализации.
Если вы посмотрите на источник, вы увидите, что writeObject()
не сохраняет массив подкачки. Вместо этого он сериализует элементы (включая нулевые значения) по одному за раз до предела size()
. Это позволяет избежать накладных расходов на сериализацию массива и особенно любых неиспользуемых слотов в конце массива. При десериализации новый массив поддержки минимально необходимого размера создается readObject()
.
Почему это должно быть временным?
Он делает это, потому что он предоставляет настраиваемые методы readObject
и writeObject
, которые лучше выполняют сериализацию, чем значение по умолчанию. В частности, метод writeObject записывает только размер и последовательность элементов. Это позволяет избежать сериализации частного объекта массива, который 1) имеет свой собственный заголовок и накладные расходы, а 2) обычно дополняется null
s. Экономия места может быть значительной.
(На самом деле, я не думаю, что поле строго должно быть объявлено как transient
вообще, но оно помогает документировать намерение разработчика.)
Почему этот класс не может быть сериализован?
Класс ArrayList
в целом может быть сериализован 1. Object[]
может быть сериализован, но они решили реализовать его по-другому.
1 - На самом деле это зависит от типов времени выполнения элементов. Например, если вы попытались сериализовать ссылки ArrayList
, содержащие Thread
, тогда вы получите исключение во время выполнения для первой ненулевой ссылки.
ArrayList
реализует Serializable
, поэтому он может быть сериализован, и именно поэтому частный массив поддержки transient
, поэтому он не сериализуется вместе с другими данными в классе, поскольку все обрабатывается ArrayList
writeObject
и readObject
.
Потому что он реализует явную сериализацию. См. ArrayList # writeObject.
Переменная не сериализуема
Переменная избыточна
ссылка: http://onjava.com/pub/a/onjava/excerpt/JavaRMI_10/index.html?page=3
Продолжая ответ на вопрос Стивена С, я хотел бы исправить его заметку об использовании переходных процессов, в случае ArrayLists
, для удобочитаемости. Это может быть лучше в качестве комментария под его ответом, но у меня пока нет такой возможности!
Хотя поле, помеченное как transient
, полезно для удобочитаемости, оно также необходимо из-за пользовательских readObject
и writeObject
вызывающих java.io.ObjectInputStream
defaultReadObject
и java.io.ObjectOutputStream
defaultWriteObject
соответственно. Эти методы сделают грязную работу по обработке сериализации всех полей, не помеченных как transient
(например, size
).
См. Исходный код для ObjectOutputStream
для получения дополнительной информации здесь: https://github.com/openjdk-mirror/jdk7u-jdk/blob/master/src/share/classes/java/io/ObjectOutputStream.java#L431