淘先锋技术网

首页 1 2 3 4 5 6 7

一,什么是序列化

对象序列化:是一个用于将对象状态转换为二进制字节流的过程,
持久化:可以将其保存到磁盘文件中或通过网络发送到任何其他程序;
反序列化:从字节流创建对象的相反的过程称为反序列化。

二,常用序列化方式

方式一:要传递的类实现Serializable接口传递对象(Java自带)

ObjectOutputStream 类用来序列化一个对象,使用ObjectOutputStream对象的writeObject()方法来进行对象的写入。
示例:

import java.io.*;
 
public class SerializeDemo
{
   public static void main(String [] args)
   {
      Employee e = new Employee();
      e.name = "Reyan Ali";
      e.address = "Phokka Kuan, Ambehta Peer";
      e.SSN = 11122333;
      e.number = 101;
      try
      {
         FileOutputStream fileOut =
         new FileOutputStream("/tmp/employee.ser");
         ObjectOutputStream out = new ObjectOutputStream(fileOut);
         out.writeObject(e);
         out.close();
         fileOut.close();
         System.out.printf("Serialized data is saved in /tmp/employee.ser");
      }catch(IOException i)
      {
          i.printStackTrace();
      }
   }
}

反序列化:使用ObjectInputStream对象的readObject()方法来读取对象。

import java.io.*;
 
public class DeserializeDemo
{
   public static void main(String [] args)
   {
      Employee e = null;
      try
      {
         FileInputStream fileIn = new FileInputStream("/tmp/employee.ser");
         ObjectInputStream in = new ObjectInputStream(fileIn);
         e = (Employee) in.readObject();
         in.close();
         fileIn.close();
      }catch(IOException i)
      {
         i.printStackTrace();
         return;
      }catch(ClassNotFoundException c)
      {
         System.out.println("Employee class not found");
         c.printStackTrace();
         return;
      }
      System.out.println("Deserialized Employee...");
      System.out.println("Name: " + e.name);
      System.out.println("Address: " + e.address);
      System.out.println("SSN: " + e.SSN);
      System.out.println("Number: " + e.number);
    }
}

忽略某个字段不序列化:

  • 使用关键字 transient

  • 使用注解 @jsonignore

  • 父类实现了序列化,子类未实现但是继承了父类,则子类默认实现序列化

  • 子类中添加writeObject和readObject 和 readObjectNoDate()抛出异常。此时子类就不会默认实现序列化。

  • 子类实现序列化接口,父类未实现,也需要在父类中添加无参构造函数,并添加writeObject和readObject方法

  • writeObject和readObject方法 是因为通过反射序列化和反序列化

  • 无参构造函数:只通过无参构造函数来拿到实例

方式二:要传递的类实现Parcelable接口传递对象(android专用)

实现
复写describeContents方法和writeToParcel方法
2、实例化静态内部对象CREATOR,实现接口Parcelable.Creator
3、自定义构造方法,私有变量的set与get

public class Pen implements Parcelable{
    private String color;
    private int size;
    
    // 系统自动添加,给createFromParcel里面用
    protected Pen(Parcel in) {
        color = in.readString();
        size = in.readInt();
    }
    public static final Creator<Pen> CREATOR = new Creator<Pen>() {
        /**
         *
         * @param in
         * @return
         * createFromParcel()方法中我们要去读取刚才写出的name和age字段,
         * 并创建一个Person对象进行返回,其中color和size都是调用Parcel的readXxx()方法读取到的,
         * 注意这里读取的顺序一定要和刚才写出的顺序完全相同。
         * 读取的工作我们利用一个构造函数帮我们完成了
         */
        @Override
        public Pen createFromParcel(Parcel in) {
            return new Pen(in); // 在构造函数里面完成了 读取 的工作
        }
        //供反序列化本类数组时调用的
        @Override
        public Pen[] newArray(int size) {
            return new Pen[size];
        }
    };
    
    @Override
    public int describeContents() {
        return 0;  // 内容接口描述,默认返回0即可。
    }
    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(color);  // 写出 color
        dest.writeInt(size);  // 写出 size
    }
    // ======分割线,写写get和set
    //个人自己添加
    public Pen() {
    }
    //个人自己添加
    public Pen(String color, int size) {
        this.color = color;
        this.size = size;
    }
    
    public String getColor() {
        return color;
    }
    public void setColor(String color) {
        this.color = color;
    }
    public int getSize() {
        return size;
    }
    public void setSize(int size) {
        this.size = size;
    }
}

两种方式对比

需要在多个部件(Activity或Service)之间通过Intent传递一些数据,简单类型(如:数字、字符串)的可以直接放入Intent。复杂类型必须实现Parcelable接口。
1)在使用内存的时候,Parcelable比Serializable性能高,所以推荐使用Parcelable。Parcelable是再内存中完成序列化和反序列化的。
2)Serializable在序列化的时候会产生大量的临时变量,从而引起频繁的GC。
3)Parcelable不能使用在要将数据存储在磁盘上的情况,因为Parcelable不能很好的保证数据的持续性在外界有变化的情况下。尽管Serializable效率低点,但此时还是建议使用Serializable 。

三,Json解析

1,定义

JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式

2,作用与特点

作用:数据标记,存储,传输
特点:
1.读写速度快
2. 解析简单
3. 轻量级
4. 独立于语言,平台

在这里插入图片描述

3,Json常见形式

1,Object

对象是一个无序的“‘名称/值’对”集合。一个对象以“{”(左括号)开始,“}”(右括号)结束。每个“名称”后跟一个“:”(冒号);“‘名称/值’ 对”之间使用“,”(逗号)分隔。
在这里插入图片描述
示例:

{
"name": "英语",
"score": 78.3
}

Array形式

数组是值(value)的有序集合。一个数组以“[”(左中括号)开始,“]”(右中括号)结束。值之间使用“,”(逗号)分隔。
在这里插入图片描述
示例:

"courses": [
{
"name": "英语",
"score": 78.3
}
]

3,value

值(value)可以是双引号括起来的字符串(string)、数值(number)、 true 、 false 、 null 、对象(object)或者数组(array)。这些结构可以嵌套。
在这里插入图片描述
示例:

{
"url": "https://qqe2.com",
"name": "欢迎使用JSON在线解析编辑器",
"array": {
"JSON校验": "http://jsonlint.qqe2.com/",
"Cron生成": "http://cron.qqe2.com/",
"JS加密解密": "http://edit.qqe2.com/"
},
"boolean": true,
"null": null,
"number": 123,
"object": {
"a": "b",
"c": "d",
"e": "f"
}
}

Json解析器

1,Json-lib

  • 原理:解析原理:基于文档驱动,需要把全部文件读入到内存中,然后遍历所有数据,根据需要检索想要的数据

2,Gson

解析流程:根据所需取的数据 建立1个对应于JSON数据的JavaBean类,即可通过简单操作解析出所需数据
Gson 不要求JavaBean类里面的属性一定全部和JSON数据里的所有key相同,可以按需取数据具体实现
序列化:Gson().toJson(object)
反序列化:Gson().fromJson(Json, Simple.class)

@Expose注解是可选择的并且提供了两个配置参数:serialize和deserialize
serialize = true 表示可以序列化, 反之不行
deserialize = true 表示可以反序列化,反之不行

Transient 关键字表示忽略此字段。不会序列化和反序列化

@SerializedName注解改变域名 ,返回fullName,但是用时为name

public class UserSimple {  
    @SerializedName("fullName")
    String name;
    String email;
    boolean isDeveloper;
    int age;
}
public class UserSimpleSerializedName {  
    @SerializedName(value = "fullName", alternate = "username")
    private String name;

    private String email;
    private boolean isDeveloper;
    private int age;
} 

在上面的模型类中,Gson将会检查到来的JSON中是否含有fullName或者username。无论是哪一个,都会映射到name属性

Gson的介绍与使用引入此篇文章
https://www.jianshu.com/p/923a9fe78108

3,FastJson

https://juejin.cn/post/6844904176003072007#heading-21

序列化:JSON.toJSONString(simple)
反序列化:
(1)JSON.parseObjec(Json, Simple.class)
(2)JSON.parseObject(JSON_OBJ_STR, new TypeReference() {})
(3)JSON.parseObject(JSON_OBJ_STR);

4,JackSon

解析过程:

  1. 类似 GSON,先创建1个对应于JSON数据的JavaBean类,再通过简单操作即可解析
  2. 与 Gson解析不同的是:GSON可按需解析,即创建的JavaBean类不一定完全涵盖所要解析
    的JSON数据,按需创建属性;但Jackson解析对应的JavaBean必须把Json数据里面的所有key
    都有所对应,即必须把JSON内的数据所有解析出来,无法按需解析
    序列化:String json = JsonUtils.toJsonString(user);

反序列化: User u = JsonUtils.parse(json, User.class);

5,Moshi(配合kotlin)

https://juejin.cn/post/6844903704278073357