对象流的作用:可以读写八种基本数据类型,还可以读写实体类对象
对象流 可以用来做 对象的序列化与反序列化 (Serialization)
1、 ObjectOutputStream 序列化:将对象转化为二进制byte流的过程,以下是对象流特有输出方法:
void writeByte(byte data)
void writeShort(short data)
void writeInt(int data)
void writeLong(long data)
void writeChar(char data)
void writeFloat(float data)
void writeDouble(double data)
void writeBoolean(boolean data)
void writeUTF(String data)
void writeObject(Object data)
2、 ObjectInputStream 反序列化:将二进制byte流转换为对象的过程,以下是对象流特有输入方法:
byte readByte()
short readShort()
int readInt()
long readLong()
char readChar()
float readFloat()
double readDouble()
boolean readBoolean()
String readUTF()
Object readObject()
一、对象序列化的条件:
只有实现了 Serializable 接口的类的对象才可以被序列化。
Serializable 接口中没有任何的方法,实现该接口的类不需要 实现额外的方法。
如果对象的属性是对象,属性对应类也必须实现 Serializable接口
二、如何实现序列化:
创建ObjectOutputStream对象
调用writeObject()输出对象
三、如何实现反序列化 :
创建ObjectInputStream对象
调用readObject()读取对象
·序列化与反序列化 :
1) 序列化能保存的元素
a) 只能保存对象的非静态成员变量
b) 不能保存任何成员方法和静态的成员变量
c) 不保存 transient 成员变量
d) 如果一个对象的成员变量是一个对象,这个对象的成员变量也会保存
e) 串行化保存的只是变量的值,对于变量的任何修饰符, 都不能保存
2) 使用对象流把一个对象写到文件时不仅保证该对象是序列化的,而且该对象的成员对象也必须是可序列化的
3) 如果一个可序列化的对象包含对某个不可序列化的对象的引用(没有实现Implements serializable),那么整个序列化操作将会失败,
并且会抛出一个 NotSerializableException。我们可以将这个引用标记为 transient,那么对象仍然可以序列化。
·对象序列化注意事项:
1) 同一个对象多次序列化的处理
a) 所有保存到磁盘中的对象都有一个序列化编号
b) 序列化一个对象中,首先检查该对象是否已经序列化过
c) 如果没有,进行序列化
d) 如果已经序列化,将不再重新序列化,而是输出编号 即可
2) 如果不希望某些属性(敏感)序列化,或不希望出现递归 序列
a) 为属性添加 transient 关键字(完成排除在序列化之外)
b) 自定义序列化(不仅可以决定哪些属性不参与序列化, 还可以定义属性具体如何序列化)
3) 序列化版本不兼容
a) 修改了实例属性后,会影响版本号,从而导致反序列化 不成功
b) 解 决 方 案 : 为 Java 对 象 指 定 序 列 化 版 本 号 serialVersionUID
实体类:
public class Student implements Serializable {
/**
*
*/
private static final long serialVersionUID = -1026226854058141848L;
//为序列化的类添加一个编号
public int id;
private String name;
private int age;
private transient String pwd; //transient修饰的属性不会被序列化,所以调用read()方法时显示为null
public static String schoolName; //静态属性也不会被序列化
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
public Student(String name, int age, String pwd) {
super();
this.name = name;
this.age = age;
this.pwd = pwd;
}
public Student() {
super();
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + ", pwd=" + pwd + ",schoolName=" + schoolName + "]";
}
}
测试类:(注意需要先写再读,即先序列化,再反序列化)
public class TestObject {
public static void main(String[] args) throws IOException, ClassNotFoundException {
//write();
read();
}
public static void write() throws IOException {
ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("E:\\a.txt"));
Student stu=new Student("李四", 18, "8888");
Student.schoolName="清华大学";
oos.writeObject(stu);
if(oos!=null) {
oos.close();
}
}
public static void read() throws IOException, ClassNotFoundException {
ObjectInputStream ois =new ObjectInputStream(new FileInputStream("E:\\a.txt"));
Student stu=(Student) ois.readObject();
System.out.println(stu);
ois.close();
}
}