zoukankan      html  css  js  c++  java
  • java transient初探

    1.关于transient的解释

    transient用来表示一个域(对象属性)不是该对象串行化(序列化)的一部分。当一个对象被串行化的时候,transient修饰的变量的值不包括在串行化的表示中,然而非transient型的变量是被包括进去的。

    2.实践证明

    A.第一步:新建一个其对象可以被序列化的类Book,源码如下:

    /**
     * 该类对象可以被序列化
     * @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;
    	}
    }

    B.第二步,编写测试类进行测试,代码如下:

    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();
    		}
    		
    	}


    C.第三步,运行,分析执行结果

    book序列化之前: id=1,name=aa,price=12.5
    book反序列化之后:id=1,name=aa,price=0.0

    从执行结果中可以发现,反序列化之后book对象的price属性变为默认值了,实践证明,被transient关键字修饰的域(属性)确实不会被序列化。

     3.困惑之处

    通过上面的实践自我感觉已经掌握了transient的用处,然而分析ArrayList源码之后又让我多了几分困惑,部分源码如下:

    public class ArrayList<E> extends AbstractList<E>
            implements List<E>, RandomAccess, Cloneable, java.io.Serializable
    {
        private static final long serialVersionUID = 8683452581122892189L;
    
        /**
         * The array buffer into which the elements of the ArrayList are stored.
         * The capacity of the ArrayList is the length of this array buffer.
         */
        private transient Object[] elementData;
    
        /**
         * The size of the ArrayList (the number of elements it contains).
         *
         * @serial
         */
        private int size;
    
        /**
         * Constructs an empty list with the specified initial capacity.
         *
         * @param   initialCapacity   the initial capacity of the list
         * @exception IllegalArgumentException if the specified initial capacity
         *            is negative
         */
        public ArrayList(int initialCapacity) {
    	super();
            if (initialCapacity < 0)
                throw new IllegalArgumentException("Illegal Capacity: "+
                                                   initialCapacity);
    	this.elementData = new Object[initialCapacity];
        }
    
        /**
         * Constructs an empty list with an initial capacity of ten.
         */
        public ArrayList() {
    	this(10);
        }
    
    .......
    }

    研究发现ArrayList的背后实际上是一个动态数组,private transient Object[] elementData;那为什么要修饰为transient呢?这样岂不是不能被序列化了?我带着疑问进行了测试,结果发现能够正常序列化和反序列化,集合中的元素也不会丢失,如果这样,那岂不与上面的实践结论相矛盾?看到下面的解释后,让我豁然开朗。

     elementData是一个缓存数组,它通常会预留一些容量,等容量不足时再扩充容量。假如现在实际有了5个元素,而elementData的大小可能是10,那么在序列化时只需要储存5个元素,数组中的最后五个元素是没有实际意义的,不需要储存。所以ArrayList的设计者将elementData设计为transient,然后在writeObject方法中手动将其序列化,并且只序列化了实际存储的那些元素,而不是整个数组


    4.再次困惑 

    LinkedList的部分代码如下:

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



    ss

  • 相关阅读:
    ThreadLocal全面解析,一篇带你入门
    StringTable字符串常量池的垃圾回收跟踪案例
    air镶边引7yue
    性能优化与团队效率
    air 错误信息一览
    AS3 使用unloadAndStop()卸载加载的swf以及里面的声音
    flash/flex/as3应用程序加载as2、as1版本的swf遇到的问题
    查看swc的代码
    chart 属性
    flex动态控制 effect
  • 原文地址:https://www.cnblogs.com/yyuuaannllii/p/3775223.html
Copyright © 2011-2022 走看看