Подтвердить что ты не робот

Почему ArrayList использует временное хранилище?

Я читал источник Java ArrayList, и я наткнулся на его объявление массива:

private transient Object[] elementData;

Почему это должно быть временным? Почему этот класс не может быть сериализован?

Спасибо за помощь!

4b9b3361

Ответ 1

Он может быть сериализован; класс ArrayList просто заботится о себе, а не использует механизм по умолчанию. Посмотрите на методы writeObject() и readObject() в этом классе, которые являются частью стандартного механизма сериализации.

Если вы посмотрите на источник, вы увидите, что writeObject() не сохраняет массив подкачки. Вместо этого он сериализует элементы (включая нулевые значения) по одному за раз до предела size(). Это позволяет избежать накладных расходов на сериализацию массива и особенно любых неиспользуемых слотов в конце массива. При десериализации новый массив поддержки минимально необходимого размера создается readObject().

Ответ 2

Почему это должно быть временным?

Он делает это, потому что он предоставляет настраиваемые методы readObject и writeObject, которые лучше выполняют сериализацию, чем значение по умолчанию. В частности, метод writeObject записывает только размер и последовательность элементов. Это позволяет избежать сериализации частного объекта массива, который 1) имеет свой собственный заголовок и накладные расходы, а 2) обычно дополняется null s. Экономия места может быть значительной.

(На самом деле, я не думаю, что поле строго должно быть объявлено как transient вообще, но оно помогает документировать намерение разработчика.)

Почему этот класс не может быть сериализован?

Класс ArrayList в целом может быть сериализован 1. Object[] может быть сериализован, но они решили реализовать его по-другому.


1 - На самом деле это зависит от типов времени выполнения элементов. Например, если вы попытались сериализовать ссылки ArrayList, содержащие Thread, тогда вы получите исключение во время выполнения для первой ненулевой ссылки.

Ответ 3

ArrayList реализует Serializable, поэтому он может быть сериализован, и именно поэтому частный массив поддержки transient, поэтому он не сериализуется вместе с другими данными в классе, поскольку все обрабатывается ArrayList writeObject и readObject.

Ответ 4

Потому что он реализует явную сериализацию. См. ArrayList # writeObject.

Ответ 5

Переменная не сериализуема

  • Если переменная не сериализуема, механизм сериализации будет генерировать исключение, когда он пытается сериализовать переменную. Чтобы этого избежать, вы можете объявить переменную переходной.

Переменная избыточна

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

ссылка: http://onjava.com/pub/a/onjava/excerpt/JavaRMI_10/index.html?page=3

Ответ 6

Продолжая ответ на вопрос Стивена С, я хотел бы исправить его заметку об использовании переходных процессов, в случае 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