现在开始补课,补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里的defaultWriteObject和ObjectInputStream里的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; }