首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > JAVA > J2SE开发 >

关于transient的困惑解决思路

2012-01-23 
关于transient的困惑前段时间复习了一下对象的序列化技术,其中涉及到了java语言规范中的transient关键字的

关于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()方法返回的结果同序列化前相同。那么这样设计的目的何在?求解中...............


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


Java code
 /**     * Save the state of this <tt>LinkedList</tt> instance to a stream (that     * is, serialize it).     *     * @serialData The size of the list (the number of elements it     *           contains) is emitted (int), followed by all of its     * elements (each an Object) in the proper order.     */    private void writeObject(java.io.ObjectOutputStream s)        throws java.io.IOException {    // Write out any hidden serialization magic    s.defaultWriteObject();        // Write out size        s.writeInt(size);    // Write out all elements in the proper order.        for (Entry e = header.next; e != header; e = e.next)            s.writeObject(e.element);    }    /**     * Reconstitute this <tt>LinkedList</tt> instance from a stream (that is     * deserialize it).     */    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();        // Initialize header        header = new Entry<E>(null, null, null);        header.next = header.previous = header;    // Read in all elements in the proper order.    for (int i=0; i<size; i++)            addBefore((E)s.readObject(), header);    }
[解决办法]
探讨

2楼说得没错,确实是那个两个方法起了作用,谢谢你啊!
起初看源码的时候没有深入研究,还很纳闷,写两个私有方法又没有调用意图何在,经2楼一提醒,我才想到了反射机制,果然在ObjectInputStream/ObjectOutputStream中通过放射调用了这两个私有方法!只是不解的是为什么要这样设计???将以下两个属性的修饰符transient去掉会有什么影响呢???
private tra……

[解决办法]
探讨

引用:

2楼说得没错,确实是那个两个方法起了作用,谢谢你啊!
起初看源码的时候没有深入研究,还很纳闷,写两个私有方法又没有调用意图何在,经2楼一提醒,我才想到了反射机制,果然在ObjectInputStream/ObjectOutputStream中通过放射调用了这两个私有方法!只是不解的是为什么要这样设计???将以下两个属性的修饰……

[解决办法]
探讨

引用:

引用:

引用:

2楼说得没错,确实是那个两个方法起了作用,谢谢你啊!
起初看源码的时候没有深入研究,还很纳闷,写两个私有方法又没有调用意图何在,经2楼一提醒,我才想到了反射机制,果然在ObjectInputStream/ObjectO……

热点排行