Java:序列化

一、序列化

1.概述

  • 对象序列化:就是将对象保存到磁盘中,或者在网络中传输对象
  • 这种机制就是使用一个字节序列表示一个对象,该字节序列包含:对象的类型、对象的数据和对象中存储的属性等信息
  • 字节序列写到文件之后,相当于文件中持久保存了一个对象的信息
  • 反之,该字节序列还可以从文件中读取回来,重构对象,对它进行反序列化

2.使用方法

  • 对象序列化流: ObjectOutputStream

  • 将Java对象的原始数据类型和图形写入OutputStream。 可以使用ObjectInputStream读取(重构)对象。 可以通过使用流的文件来实现对象的持久存储。 如果流是网络套接字流,则可以在另一个主机上或另一个进程中重构对象

  • 对象反序列化流: ObjectInputStream

    • ObjectInputStream反序列化先前使用ObjectOutputStream编写的原始数据和对象
  • 注意

    • 一个对象要想被序列化,该对象所属的类必须必须实现Serializable 接口
    • Serializable是一个标记接口,实现该接口,不需要重写任何方法
  • 构造方法

    方法名 说明
    ObjectOutputStream(OutputStream out) 创建一个写入指定的OutputStream的ObjectOutputStream
    ObjectInputStream(InputStream in) 创建从指定的InputStream读取的ObjectInputStream
  • 对象方法

    方法名 说明
    void writeObject(Object obj) 将指定的对象写入ObjectOutputStream
    Object readObject() 从ObjectInputStream读取一个对象
  • User类:serialVersionUID&transient的使用


import java.io.Serializable;

//如果想要这个类的对象能被序列化,那么这个类必须要实现一个接口.Serializable

//Serializable 接口的意义
//称之为是一个标记性接口,里面没有任何的抽象方法
//只要一个类实现了这个Serializable接口,那么就表示这个类的对象可以被序列化.
public class User implements Serializable {
    //serialVersionUID 序列号
    //如果我们自己没有定义,那么虚拟机会根据类中的信息会自动的计算出一个序列号.
    //问题:如果我们修改了类中的信息.那么虚拟机会再次计算出一个序列号.

    //第一步:把User对象序列化到本地. --- -5824992206458892149
    //第二步:修改了javabean类. 导致 --- 类中的序列号 4900133124572371851
    //第三步:把文件中的对象读到内存. 本地中的序列号和类中的序列号不一致了.

    //解决?
    //不让虚拟机帮我们自动计算,我们自己手动给出.而且这个值不要变.

    private static final long serialVersionUID = 1L;

    private String username;
    private transient String password;

    public User() {
    }

    public User(String username, String password) {
        this.username = username;
        this.password = password;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

  • 测试存取对象
static void method1() throws IOException, ClassNotFoundException {
    User user = new User("zhangsan","qwer");
    // 序列化
    ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("a.txt"));
    oos.writeObject(user);
    oos.close();
    // 反序列化
    ObjectInputStream ois = new ObjectInputStream(new FileInputStream("a.txt"));
    User o = (User) ois.readObject();
    System.out.println(o);
    ois.close();
}
  • 测试存取集合
static void test() throws IOException, ClassNotFoundException {
    //1.创建集合
    ArrayList<Student> arrayList = new ArrayList<>();
    for (int i = 0; i < 3; i++) {
        Student s = new Student("佟丽娅:"+ String.valueOf(i),30+i);
        arrayList.add(s);
    }

    //2.将集合对象序列化到文件中
    ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("oos.txt"));
    oos.writeObject(arrayList);
    oos.close();

    //3.将文件中的对象数据,读取到内存中
    ObjectInputStream ois = new ObjectInputStream(new FileInputStream("oos.txt"));
    Object obj = ois.readObject();
    ois.close();

    //取出集合对象
    ArrayList<Student> arrayList1 = (ArrayList<Student>)obj;
    for (Student s : arrayList) {
        System.out.println(s.getName() + "," + s.getAge());
    }
}

二、Properties集合

1、概述

  • 是一个Map体系的集合类
  • Properties可以保存到流中或从流中加载
  • 属性列表中的每个键及其对应的值都是一个字符串

2、常用方法

方法名 说明
Object setProperty(String key, String value) 设置集合的键和值,都是String类型,底层调用 Hashtable方法 put
String getProperty(String key) 使用此属性列表中指定的键搜索属性
Set<String> stringPropertyNames() 从该属性列表中返回一个不可修改的键集,其中键及其对应的值是字符串
public synchronized V put(K key, V value) 设置集合的键和值
public Set<K> keySet() 从该属性列表中返回一个不可修改的键集
static void test1(){
    // Properties<String,String> prop = new Properties<String,String>(); //错误
    Properties prop = new Properties();
    //设置集合的键和值,都是String类型
    for (int i = 0; i < 3; i++) {
        prop.setProperty("佟丽娅:"+ String.valueOf(i), String.valueOf("年龄" + i));
    }
    for (int i = 3; i < 6; i++) {
        prop.put("佟丽娅:"+ String.valueOf(i),30+i);
    }

    //使用此属性列表中指定的键搜索属性
    System.out.println(prop.getProperty("佟丽娅:3"));
    System.out.println(prop);

    //遍历集合
    Set<Object> keySet = prop.keySet();
    for (Object key : keySet) {
        Object value = prop.get(key);
        System.out.println(key + "," + value);
    }

    //从该属性列表中返回一个不可修改的键集,其中键及其对应的值是字符串
    Set<String> names = prop.stringPropertyNames();
    for (String key : names) {
        String value = prop.getProperty(key);
        System.out.println(key + "," + value);
    }
}

3Properties和IO流相结合

  • 和IO流结合的方法

    方法名 说明
    void load(Reader reader) 从输入字符流读取属性列表(键和元素对)
    void store(Writer writer, String comments) 将此属性列表(键和元素对)写入此 Properties表中,以适合使用 load(Reader)方法的格式写入输出字符流
private static void test2() throws IOException {
    Properties prop1 = new Properties();
    for (int i = 0; i < 3; i++) {
        prop1.setProperty("佟丽娅:"+ String.valueOf(i), String.valueOf("年龄" + i));
    }

    // 创建文件
    FileWriter fw = new FileWriter("fw.txt");
    // 保存Properties对象
    prop1.store(fw,null);
    fw.close();

    Properties prop2 = new Properties();
    // 读取文件
    FileReader fr = new FileReader("fw.txt");
    // 读取Properties对象
    prop2.load(fr);
    fr.close();

    System.out.println(prop2);
}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容