保存对象
串流(Stream)
- 串流分为连接用串流(connnection streams)和链接用串流(chain streams),连接用串流通常来连接来源或者目的地, typically a file, network socket connection, or the console. 链接用串流不能用来连接源或者目的地。Chain streams cannot connect to a source or destination and must be chained to a connection (or other) stream.
File
- File对象代表文件或者目录的路径,但不代表文件或者目录本身
//创建代表已有文件的File对象
File f = new File("Mycode.txt");
//创建新的目录
File dir = new File("MyDocuments");
dir.mkdir();
//列出目录下的内容
if(dir.isDirectory()){
String[] dirContents = dir.list();}
//取得绝对路径
System.out.println(dir.getAbsolutePath());
//删除文件或目录
boolean isDeleted = f.delete();
序列化(Serialization)
- 对象有状态和行为两种属性,行为存储在类中,状态存储在每个个别的对象,需要存储对象状态的时候使用序列化(Serialization)
//ObjectOutputStream与FileOutputStream都为OutputStream的子类,OutputStream为一个抽象类。
//左边为对象字节流,右边为文件字节流,write向右,read向左
//characterOne必须是一个可被序列化的对象,需要实现Serializable接口才可以
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("MyGame.ser"));
oos.writeObject(characterOne);
oos.close();
当对象被序列化时,被该对象引用的实例化变量也被序列化,并且所有被引用的对象也都会被序列化
序列化版图中如果有任何一个变量没有序列化成功,则整个序列化都失败。例如序列化Pond对象时,如果Duck类没有实现Serializable接口,则序列化失败
如果某实例变量不能或不应该被序列化时,就把它标记为transient ,则序列化过程可以跳过这个实例变量。当序列化还原的时候,被transient的实例变量会以值为null的对象引用或0,false等默认primitive主数据类型返回
public class Pond{
public String name;
public Duck duck = new Duck();
}
public class Pond{
public String name;
public transient Duck duck = new Duck();
}
如果一个对象序列化后被还原,且他的父类是不可序列化的,则父类的构造函数会跟着创建新的对象时一起执行
如果两个对象都有引用实例变量指向相同的对象,那么他们在被序列化的时候只有一个引用对象会被存储,另一个会复原成指向该引用
静态变量不会被序列化,因为static代表每个类一个而不是每个变量一个,所以对象被还原时,静态变量会维持类中原本的样子,而不是存储时的样子
如果你的类可能在产生序列化对象之后继续演变,则会有与序列化时不同的serialVersionUID,那么在解序列化时则会失败。所以如果你的类可能在产生序列化对象之后继续演变,你可以手工获得版本ID,然后将其拷贝到类上,但你必须确定你的改变不会对解序列化造成伤害
解序列化(Deserialization)
//ObjectInputStream与FileInputStream都为InputStream的子类,InputStream为一个抽象类。
//左边为对象字节流,右边为文件字节流,write向右,read向左
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("MyGame.ser"));
Object one = ois.readObject();
Object two = ois.readObject();
GameCharacter elf = (GameCharacter) one;
GameCharacter troll = (GameCharacter) two;
ois.close();
解序列化时Java虚拟机会尝试寻找和加载对象的类,如果找不到或无法加载该类,则会抛出异常。对于通过网络传送序列化对象来说,有一种机制可以让类使用URL来指定自己的位置,让你可以把序列化对象当作参数的一部分来传送,如果接受此调用的Java虚拟机没有此类,则它可以自动使用URL来取回并加载该类
解序列化后新的对象会被配置在堆上,但构造函数不会执行,因为这样会把对象的状态抹去变成全新的状态。如果对象在继承树上有个不可序列化的祖先类,则该不可序列化类以及在它之上的类(就算可序列化也一样)构造函数都会执行,且一经启动,无法停止