Java - why transient member variables used so widely in Java standard library?
Asked Answered
F

2

6

After looking the source code of some Java Collection classes, I found that the member variables are always being modified by using transient.

For instance, the LinkedList source code:

public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, Deque<E>, Cloneable, java.io.Serializable
{
    private transient Entry<E> header = new Entry<E>(null, null, null);
    private transient int size = 0;

    public LinkedList() 
    {
        header.next = header.previous = header;
    }

    public LinkedList(Collection<? extends E> c) {
        this();
        addAll(c);
    }

    // ...other stuff
}

Of course, not only LinkedList uses transient, almost every Java collection classes use transient to modify at least half of their member variables.

So, my question is: why transient used so widely in the Java standard library?

(Of course everyone knows the definition and usage of transient, but that's not my question:)

Fraternize answered 11/11, 2015 at 9:29 Comment(2)
This may be a better duplicate: #9848629Seventeen
Or this: #25926512Seventeen
S
7

From serialization point of view transient variables will not be serialized when serializing the whole object.

When you don't want some variable to be serialized you make it transient

From your example LinkedList is serializable. If you look carefully all the variable that are made transient are maintained programmatically. SO there is no need to persist them.

For example size, when you are reading back any serialized object you are reading just Node<E> and maintaining the size programmatically. So there is no need to serialize the size. Remember the real data of a LinkedList is not its size. If you have the real data which are the entries you can calculate its size any time and its easier this way.

For Reference please have a look.

@SuppressWarnings("unchecked")
private void readObject(java.io.ObjectInputStream s)
    throws java.io.IOException, ClassNotFoundException {
    // Read in any hidden serialization magic
    s.defaultReadObject();

    // Read in size
    int size = s.readInt();

    // Read in all elements in the proper order.
    for (int i = 0; i < size; i++)
        linkLast((E)s.readObject());
}

void linkLast(E e) {
    final Node<E> l = last;
    final Node<E> newNode = new Node<>(l, e, null);
    last = newNode;
    if (l == null)
        first = newNode;
    else
        l.next = newNode;
    size++;
    modCount++;
}
Sunwise answered 11/11, 2015 at 9:31 Comment(2)
So, for example, since which node the current head is pointing is not important for a just-deserailized LinkedList, we don't have to keep the information while serializing the while object?Fraternize
Yes, i can say that about size, if you see the linkLast() method you will understand. But the source code i have here doesn't have header. which version you are reading actually ?Sunwise
L
1

When you're writing a non-trivial serializable class (something that is considerably more complicated than a POJO), it is generally a good idea to decouple what the class represents from the actual implementation.

One way to do this is via transient fields and providing readObject()/writeObject() methods that control what values are written in the serialized form and how to initialise transient fields on deserialization.

An even more robust solution is serialization proxies, they actually serialize a completely different object instead, using readResolve()/writeReplace(). (An example of this pattern can be found in EnumSet.)

The main advantage of these techniques is that they allow you to change the implementation without having to change the serialized form of the class. This is a good thing because if you're writing an API, the serialized form of your API objects is part of the public API, it represents a commitment that objects serialized with a previous version will be deserializable with later versions. (Or your API will end up like Swing, where all the class Javadocs carry an ugly warning about it.)

They also offer some protection against maliciously crafted serialized objects breaking your class invariants. (Imagine if the linked list was serialized as is, and someone modified the result so that an entry points to itself as its successor, resulting in iterations running in an infinite loop.)

Leslie answered 11/11, 2015 at 9:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.