Collection-ArrayList-Transient及序列化

xiaoxiao2021-02-28  127

现在开始补课,补Java基础知识(这些应该是早就会的,现在才开始系统的学,但也没关系吧,争取6个月能够深入了解)。

首先看集合,引一个图

先从ArrayList看起,类定义开始是

private transient Object[] elementData;

transient不懂。看了一下是短期存在內存的不能持久化的变量,序列化的时候会跳过transient的变量。如密码等。上例的elementData为什么声明为transient?是由于elementData有预留,不是整个数组都有数,通过writeObject将有数的部分持久化,elementData不进行持久化。

transient的使用说明:

1.一旦变量被transient修饰,变量将不再是持久化的一部分,该变量在序列化后无法显示(如上描述)。

2.静态变量不管是否被transient修饰,都不被序列化。

序列化:如果需要序列化只需要实现Serializable接口。然后可以用ObjectOutputStream将该对象保存或发送给其他主机。所有的non-transient和non-static字段都将被序列化,并且由反序列化构造出一模一样的对象。readObject和writeObject是自定义序列化方法,如果用户定义了自己的readObject和writeObject,虚拟机会使用自定的持久化方法,如果没有就调用ObjectOutputStream里的defaultWriteObjectObjectInputStream里的defaultReadObject

ArrayList的readObject和writeObject实现:

private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { // Read in size, and any hidden stuff s.defaultReadObject(); // Read in array length and allocate array int arrayLength = s.readInt(); Object[] a = elementData = new Object[arrayLength]; // Read in all elements in the proper order. for (int i=0; i<size; i++) a[i] = s.readObject(); }

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 array length s.writeInt(elementData.length); // 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(); } }

调用方法 List<Integer> list = new ArrayList(); list.add(1); list.add(2); list.add(3); try { ObjectOutputStream os = new ObjectOutputStream( new FileOutputStream("C:/a.txt")); os.writeObject(list); // 将User对象写进文件 os.flush(); os.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } try { ObjectInputStream is = new ObjectInputStream(new FileInputStream( "C:/a.txt")); List<Integer> ls = (ArrayList) is.readObject(); // 从流中读取User的数据 is.close(); System.out.println("\nread after Serializable: "); System.out.println("1: " + ls.get(0)); System.out.println("2: " + ls.get(1)); System.out.println("3: " + ls.get(2)); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); }

todo:  后续了解kryo序列化实现

ArrayList允许插入空,也允许重复。

所以在很多操作的时候要注意可能为null,如remove操作,先对null做判断,否则调用null的equals报空指针异常:

public boolean remove(Object o) { if (o == null) { for (int index = 0; index < size; index++) if (elementData[index] == null) { fastRemove(index); return true; } } else { for (int index = 0; index < size; index++) if (o.equals(elementData[index])) { fastRemove(index); return true; } } return false; }

转载请注明原文地址: https://www.6miu.com/read-30124.html

最新回复(0)