对象流是处理流的一种,用于将内存中的对象写入到数据源,并且能够将对象从数据源还原到内存。
将对象写入到数据源的过程称为对象的序列化。对象的序列化过程中,对象转化为与平台无关的二进制序列,通过对象流将二进制序列写入本地磁盘,或者将二进制序列传输到另一网络节点。 实现对象序列化的流:ObjectOutputStream.
ObjectOutputStream是处理流的一种。ObjectOutputStream类继承OutputStream抽象类,并且实现ObjectOutput接口和DataOutput接口。
将对象从数据源还原到内存的过程成为反序列化。实现对象反序列化的流:ObjectInputStream.
ObjectInputStream是处理流的一种。ObjectInputStream类继承InputStream抽象类,并且实现ObjectInput接口和DataInput接口。
不是所有类型的对象都能被序列化,只有可序列化的对象才能被序列化。使用对象流序列化不可序列化的对象时,将抛NotSerializableException.可使用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 --------------------