java中的序列化和反序列化

2021-04-09 07:26

阅读:532

标签:hidden   oid   NPU   aci   处理   int()   ring   checked   lan   

介绍

序列化就是将对象转换成字节序列,反序列化就是将字节序列转换成对象。

使用

默认序列化和反序列化

public class Client {
  public static void main(String[] args) {
    User user = new User();
    user.setUserName("lisi");
    System.out.println(user);
    byte[] data = serialize(user);
    User newUser = deserialize(data, User.class);
    System.out.println(newUser);
    System.out.println(user == newUser);
  }

// 将一个对象序列化成字节序列
  private static byte[] serialize(Object obj) {
    try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
         ObjectOutputStream oos = new ObjectOutputStream(baos);) {
      oos.writeObject(obj);
      return baos.toByteArray();
    } catch (IOException e) {
      e.printStackTrace();
    }
    return null;
  }
// 将字节序列反序列化成指定类型的对象
  private static  T deserialize(byte[] data, Class clazz) {
    try (ByteArrayInputStream bais = new ByteArrayInputStream(data);
         ObjectInputStream bis = new ObjectInputStream(bais)) {
      Object obj = bis.readObject();
      return clazz.cast(obj);
    } catch (IOException | ClassNotFoundException e) {
      e.printStackTrace();
    }
    return null;
  }

  @Setter
  @Getter
  @ToString
  public static class User implements Serializable {
    private String userName;
  }
}

一个类要序列化必须实现Serializable接口,序列化字段为非static非transient修饰,
技术图片

从结果可以看到反序列化出的对象是一个新的对象。

自定义序列化和反序列化

public class Client {
  public static void main(String[] args) {
    User user = new User();
    user.setUserName("lisi");
    System.out.println(user);
    byte[] data = serialize(user);
    User newUser = deserialize(data, User.class);
    System.out.println(newUser);
    System.out.println(user == newUser);
  }

  private static byte[] serialize(Object obj) {
    try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
         ObjectOutputStream oos = new ObjectOutputStream(baos);) {
      oos.writeObject(obj);
      return baos.toByteArray();
    } catch (IOException e) {
      e.printStackTrace();
    }
    return null;
  }

  private static  T deserialize(byte[] data, Class clazz) {
    try (ByteArrayInputStream bais = new ByteArrayInputStream(data);
         ObjectInputStream bis = new ObjectInputStream(bais)) {
      Object obj = bis.readObject();
      return clazz.cast(obj);
    } catch (IOException | ClassNotFoundException e) {
      e.printStackTrace();
    }
    return null;
  }

  @Setter
  @Getter
  @ToString
  public static class User implements Serializable {
    private String userName;
// 自定义序列化过程
    private void writeObject(ObjectOutputStream oos) throws IOException {
// 默认序列化逻辑
      oos.defaultWriteObject();
// 将用户名长度序列化
      oos.writeInt(userName.length());
    }
// 自定义反序列化过程
    private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
// 默认反序列化逻辑
      ois.defaultReadObject();
// 读取用户名长度
      System.out.println(ois.readInt());
    }
  }
}

自定义序列化必须添加writeObject方法,必须为private非static,参数类型为ObjectOutputStream,返回类型为void。
自定义反序列化必须添加readObject方法,必须为private非static,参数类型为ObjectInputStream,返回类型为void。
技术图片
技术图片
HashMap就是通过自定义来实现序列化和反序列化的。

/**
     * Save the state of the HashMap instance to a stream (i.e.,
     * serialize it).
     *
     * @serialData The capacity of the HashMap (the length of the
     *             bucket array) is emitted (int), followed by the
     *             size (an int, the number of key-value
     *             mappings), followed by the key (Object) and value (Object)
     *             for each key-value mapping.  The key-value mappings are
     *             emitted in no particular order.
     */
    private void writeObject(java.io.ObjectOutputStream s)
        throws IOException {
        int buckets = capacity();
        // Write out the threshold, loadfactor, and any hidden stuff
        s.defaultWriteObject();
        s.writeInt(buckets);
        s.writeInt(size);
        internalWriteEntries(s);
    }

    /**
     * Reconstitute the {@code HashMap} instance from a stream (i.e.,
     * deserialize it).
     */
    private void readObject(java.io.ObjectInputStream s)
        throws IOException, ClassNotFoundException {
        // Read in the threshold (ignored), loadfactor, and any hidden stuff
        s.defaultReadObject();
        reinitialize();
        if (loadFactor  0) { // (if zero, use defaults)
            // Size the table using given load factor only if within
            // range of 0.25...4.0
            float lf = Math.min(Math.max(0.25f, loadFactor), 4.0f);
            float fc = (float)mappings / lf + 1.0f;
            int cap = ((fc = MAXIMUM_CAPACITY) ?
                       MAXIMUM_CAPACITY :
                       tableSizeFor((int)fc));
            float ft = (float)cap * lf;
            threshold = ((cap [] tab = (Node[])new Node[cap];
            table = tab;

            // Read the keys and values, and put the mappings in the HashMap
            for (int i = 0; i 

更彻底的自定义

public class Client {
  public static void main(String[] args) {
    User user = new User();
    user.setUserName("lisi");
    System.out.println(user);
    byte[] data = serialize(user);
    User newUser = deserialize(data, User.class);
    System.out.println(newUser);
    System.out.println(user == newUser);
  }

  private static byte[] serialize(Object obj) {
    try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
         ObjectOutputStream oos = new ObjectOutputStream(baos);) {
      oos.writeObject(obj);
      return baos.toByteArray();
    } catch (IOException e) {
      e.printStackTrace();
    }
    return null;
  }

  private static  T deserialize(byte[] data, Class clazz) {
    try (ByteArrayInputStream bais = new ByteArrayInputStream(data);
         ObjectInputStream bis = new ObjectInputStream(bais)) {
      Object obj = bis.readObject();
      return clazz.cast(obj);
    } catch (IOException | ClassNotFoundException e) {
      e.printStackTrace();
    }
    return null;
  }

  @Setter
  @Getter
  @ToString
  public static class User implements Serializable {
    private String userName;
// 替换序列化对象
    private Object writeReplace() {
      User user = new User();
      user.setUserName(userName);
      return user;
    }

// 处理反序列出的对象
    private Object readResolve() {
      userName = "lisi1";
      return this;
    }
  }
}

writeReplace方法会在真正的序列化执行之前执行,会替换我们的待序列化对象,readResolve会在反序列化执行之后执行,就可以对结果做一些后置处理。通过readResolve我们可以进行单例的保护性恢复,直接返回单例实例。

java中的序列化和反序列化

标签:hidden   oid   NPU   aci   处理   int()   ring   checked   lan   

原文地址:https://www.cnblogs.com/strongmore/p/13376299.html


评论


亲,登录后才可以留言!