Почему Java ArrayList явно записывает поле размера в поток сериализации? - PullRequest
0 голосов
/ 07 октября 2018

Начиная с Java 8, ArrayList использует следующие методы writeObject и readObject для сериализации:

/**
     * Save the state of the <tt>ArrayList</tt> instance to a stream (that
     * is, serialize it).
     *
     * @serialData The length of the array backing the <tt>ArrayList</tt>
     *             instance is emitted (int), followed by all of its elements
     *             (each an <tt>Object</tt>) in the proper order.
     */
    private void writeObject(java.io.ObjectOutputStream s)
        throws java.io.IOException{
        // Write out element count, and any hidden stuff
        int expectedModCount = modCount;
        s.defaultWriteObject();

        // Write out size as capacity for behavioural compatibility with clone()
        s.writeInt(size);

        // Write out all elements in the proper order.
        for (int i=0; i<size; i++) {
            s.writeObject(elementData[i]);
        }

        if (modCount != expectedModCount) {
            throw new ConcurrentModificationException();
        }
    }

    /**
     * Reconstitute the <tt>ArrayList</tt> instance from a stream (that is,
     * deserialize it).
     */
    private void readObject(java.io.ObjectInputStream s)
        throws java.io.IOException, ClassNotFoundException {
        elementData = EMPTY_ELEMENTDATA;

        // Read in size, and any hidden stuff
        s.defaultReadObject();

        // Read in capacity
        s.readInt(); // ignored

        if (size > 0) {
            // be like clone(), allocate array based upon size not capacity
            ensureCapacityInternal(size);

            Object[] a = elementData;
            // Read in all elements in the proper order.
            for (int i=0; i<size; i++) {
                a[i] = s.readObject();
            }
        }
    }

ArrayList.size поле имеет только модификатор private.Сериализуется методом out.defaultWriteObject.И он не используется в методе readObject (я имею в виду десереализованное значение не используется).Почему size добавляется в поток сериализации во второй раз с s.writeInt(size);?Я видел, есть комментарий, как // Write out size as capacity for behavioural compatibility with clone().Но я не могу понять связь между size, размером двойной сериализации в writeObjectMethod и clone().

1 Ответ

0 голосов
/ 08 октября 2018

Обычно такие вещи предназначены для совместимости версий.Спецификация говорит:

Длина массива, поддерживающего экземпляр ArrayList, выдается (int), за которым следуют все его элементы (каждый объект) в правильном порядке.

По общему признанию, спецификация обычно отсутствует или неверна.В любом случае он должен быть совместим по чтению и записи с тем, что делал JRE 1.2.0.

Я сейчас проверил, более старые версии использовали это как емкость.Поле емкости отсутствует, так как истинное значение может быть получено elementData.length в экземпляре, но иначе не записывается в поток.

...