日期:2014-05-20  浏览次数:20799 次

关于transient的困惑
前段时间复习了一下对象的序列化技术,其中涉及到了java语言规范中的transient关键字的用法,根据官方的解释,如果一个对象的属性用该关键字修饰,那么在序列化对象的时候,将忽略该属性(即不会进行存储,反序列化时该属性值将丢失)。

1.新建一个实现Serializable接口的类
Java code

/**
 * 该类对象可以被序列化
 * @author yuanli
 *
 */
public class Book implements Serializable {
    /**
     * 
     */
    private static final long serialVersionUID = 3173949523199923358L;
    private int id;
    private String name;
    private transient float price;
    
    public Book() {
        super();
    }

    public Book(int id, String name, float price) {
        super();
        this.id = id;
        this.name = name;
        this.price = price;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public float getPrice() {
        return price;
    }

    public void setPrice(float price) {
        this.price = price;
    }
    
    @Override
    public String toString() {
        return "id=" + this.id + ",name=" + this.name + ",price=" + this.price;
    }
}



2.编写一个测试类
Java code

public class Test {

public static void main(String[] args) {
   Test t = new Test();
   t.testTransient();
}

public void testTransient() {
        
        try {
            Book book = new Book(1,"aa",12.5f);
            System.out.println("book序列化之前: " + book.toString());
            
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(baos);
            //序列化book对象
            oos.writeObject(book);
            
            //反序列化book对象
            ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()));
            Book book_serializable = (Book)ois.readObject();
            System.out.println("book反序列化之后:" + book_serializable.toString());
            
            
        } catch (Exception e) {
            e.printStackTrace();
        }
        
    }
}


3.测试结果如下:
book序列化之前: id=1,name=aa,price=12.5
book反序列化之后:id=1,name=aa,price=0.0
从执行结果中可以发现,反序列化之后book对象的price属性变为默认值了,实践证明,被transient关键字修饰的域(属性)确实不会被序列化

4.但是下面的代码让我困惑
Java 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;

    /**
     * Constructs an empty list.
     */
    public LinkedList() {
        header.next = header.previous = header;
    }

    /**
     * Constructs a list containing the elements of the specified
     * collection, in the order they are returned by the collection's
     * iterator.
     *
     * @param  c the collection whose elements are to be placed into this list
     * @throws NullPointerException if the specified collection is null
     */
    public LinkedList(Collection<? extends E> c) {
    this();
    addAll(c);
    }
    ......
        /**
     * Returns the number of elements in this list.
     *
     * @return the number of elements in this list
     */
    public int size() {
    return size;
    }
    ......
}


研究LinkedList源码发现size和head属性被transient修饰,这样的属性应该不会被序列化,可实践证明可以正常序列化,反序列化后调用size()方法返回的结果同序列化前相同。那么这样设计的目的何在?求解中...............


------解决方案--------------------
说的没错,但是你大概还没有看完源码
它还有俩私有方法是进行写入对象和读取对象的