文章目录
概述
对象流是处理流的一种,用于将内存中的对象写入到数据源,并且能够将对象从数据源还原到内存。
序列化
概述
将对象写入到数据源的过程称为对象的序列化。对象的序列化过程中,对象转化为与平台无关的二进制序列,通过对象流将二进制序列写入本地磁盘,或者将二进制序列传输到另一网络节点。
实现对象序列化的流:ObjectOutputStream
.
ObjectOutputStream
ObjectOutputStream
是处理流的一种。ObjectOutputStream
类继承OutputStream
抽象类,并且实现ObjectOutput
接口和DataOutput
接口。
构造器
public ObjectOutputStream(OutputStream out) throws IOException {}
常用方法
/* 刷新流 */
public void flush() throws IOException {}
public void write(int val) throws IOException {}
public void write(byte[] buf) throws IOException {}
public void write(byte[] buf,int off,int len) throws IOException {}
public void writeBoolean(boolean val) throws IOException {}
public void writeInt(int val) throws IOException {}
public void writeFloat(float val) throws IOException {}
public void writeDouble(double val) throws IOException {}
public void writeChar(int val) throws IOException {}
public void writeByte(int val) throws IOException {}
public void writeLong(long val) throws IOException {}
public void writeShort(short val) throws IOException {}
public void writeChars(String str) throws IOException {}
public void writeBytes(String str) throws IOException {}
public void writeUTF(String str) throws IOException {}
public void close() throws IOException {}
/* 写入指定对象到流 */
public final void writeObject(Object obj) throws IOException {}
反序列化
概述
将对象从数据源还原到内存的过程成为反序列化。实现对象反序列化的流:ObjectInputStream
.
ObjectInputStream
ObjectInputStream
是处理流的一种。ObjectInputStream
类继承InputStream
抽象类,并且实现ObjectInput
接口和DataInput
接口。
构造器
public ObjectInputStream(InputStream in) throws IOException {}
常用方法
public void available() throws IOException {}
public int read() throws IOException {}
public int read(byte[] buf,int off,int len) throws IOException {}
public boolean readBoolean() throws IOException {}
public int readInt() throws IOException {}
public float readFloat() throws IOException {}
public double readDouble() throws IOException {}
public char readChar() throws IOException {}
public byte readByte() throws IOException {}
public long readLong() throws IOException {}
public short readShort() throws IOException {}
public String readUTF() throws IOException {}
public void close throws IOException {}
/* 从流读出一个对象 */
/* 注意:
1.如果数据源中存在多种类型的对象序列,使用readObject()读取对象时注意类型匹配。
一般要求实例引用按照writeObject()写入的顺序接收readObject()的返回。
2.在数据源的末尾(没有更多对象序列时)使用readObject()会抛java.io.EOFException. */
public final Object readObject() throws IOException,
ClassNotFoundException {}
对象可序列化
概述
不是所有类型的对象都能被序列化,只有可序列化的对象才能被序列化。使用对象流序列化不可序列化的对象时,将抛NotSerializableException
.可使用Serializable
接口使对象可序列化。
Serializable
Serializable
是java.io
包下的标记接口(空接口),实现Serializable
接口可使对象可序列化。
类实现Serializable
接口时只需要显示指定Serializable
接口中的静态常量:
static final long serialVersionUID = 42L;
serialVersionUID
用于标记类的序列化版本。未显式指明时,系统将根据内部细节自动分配值。对于类的不同实例变量,serialVersionUID
值可能分配不同。如果使用不同的实例变量接收反序列化的结果,系统会认为序列化版本不一致,抛InvalidCastException
.
因此,必须显式指定SerialVersionUID
的值(任意即可)。
public class Person implements Serializable {
/* 任意指定,无具体限制 */
/* 没有引用价值的常量,推荐使用 private 修饰 */
private static final long serialVersionUID = 5201314L;
}
对象可序列化的注意:
①使对象可序列化时,要求对象的所有属性均为可序列化的。Java中的基本数据类型和String
都是可序列化的。
②使对象可序列化时,对象类中的静态成员不被序列化,因为静态成员归属于类,而并非归属于对象。
③对象中transient
关键字修饰的成员不被序列化。如果要求对象中的某些成员不被序列化,可使用transient
关键字修饰目标成员。
对象流使用示例
Account.java
public class Account implements Serializable {
//任意指定serialVersionUID的值
private static final long serialVersionUID = 1003L;
private String name;
private long number;
private String password;
private static final String sp = File.separator;
//账户存储文件
private static final File savePath = new File("F:"+sp+"Desktop"+sp+"account.txt");
public Account(String name,long number,String password) {
this.name = name;
this.number = number;
this.password = password;
}
public void setName(String name) {this.name = name;}
public String getName() {return name;}
public void setNumber(long number) {this.number = number;}
public long getNumber() {return number;}
public void setPassword(String password) {this.password = password;}
public String getPassword() {return password;}
public void save() {
ObjectOutputStream oos = null;
try{
//覆盖原数据
oos = new ObjectOutputStream(new FileOutputStream(savePath,false));
oos.writeObject(this);
oos.flush();
} catch(IOException e){
e.printStackTrace();
} finally{
if(oos != null){
try{
oos.close();
} catch(IOException e){
e.printStackTrace();
}
}
}
}
//一台设备只有一个账户,使用静态方法获取
public static Account getAccount() {
ObjectInputStream ois = null;
Account a = null;
try{
ois = new ObjectInputStream(new FileInputStream(savePath));
a = (Account) ois.readObject();
} catch(Exception e){
e.printStackTrace();
} finally{
if(ois != null){
try{
ois.close();
} catch(IOException e){
e.printStackTrace();
}
}
}
return a;
}
@Override
public String toString(){
String str = "--------------------\n"
+ "name : " + name
+ "\n--------------------\n"
+ "number : " + number
+ "\n--------------------\n"
+ "password : " + password
+ "\n--------------------\n";
return str;
}
}
Main.java
public class Main {
public static void main(String[] args) {
Account account = new Account("Tony",18372602180L,"123456789");
account.save();
System.out.println(Account.getAccount());
//更改密码
account.setPassword("abc.123");
account.save();
System.out.println(Account.getAccount());
}
}
运行结果:
--------------------
name : Tony
--------------------
number : 18372602180
--------------------
password : 123456789
--------------------
--------------------
name : Tony
--------------------
number : 18372602180
--------------------
password : abc.123
--------------------