对象的序列化与反序列化-创新互联

文章目录
  • 目标
  • 什么是序列化和反序列化
  • 使用Serializable
    • 序列化
    • 反序列化
    • 完整实现
  • 使用**Parcelable**
    • 序列化
    • 反序列化
    • 完整实现
  • 使用Json
    • 编写和校验Json串
    • 使用Gson
      • 序列化
      • 反序列化
    • 完整实现
  • 控制序列化和反序列化
    • @Serialization
    • @Expose
    • static关键字
    • transient关键字

目前创新互联建站已为上1000家的企业提供了网站建设、域名、虚拟主机、网站托管、服务器租用、企业网站设计、儋州网站维护等服务,公司将坚持客户导向、应用为本的策略,正道将秉承"和谐、参与、激情"的文化,与客户和合作伙伴齐心协力一起成长,共同发展。目标

本文中介绍三种Android中常见的序列化的使用

  • 使用JDK提供的Serializable
  • 使用Android提供的Percelable
  • 使用Gson对Json进行使用
什么是序列化和反序列化

序列化是把对象以二进制的形式写入硬盘或者文件中,这样对象就能存入数据库、文件中或者在网络上进行传输。

反序列化是把二进制的对象数据读取出来并还原成对象的过程,这个对象的数据和序列化之前是一样的。

使用Serializable

使用Serializable方式进行序列化,需要让要序列化的对象implements Serializable接口。

  • serialVersionUID:建议主动生成一个固定的序列号。Idea或者AS中可以通过系统设置,让系统自己生成这个ID,setting—>Inspections->输入关键词UID->Serializable class...,然后在代码中,点击点击类名:Alt+Enter,就能生成UID.

    如果不主动为这个字段设值,java会以这个对象中的属性为这个字段计算一个serialVersionUID。所以如果当前对象的类中新增一个属性,那么serialVersionUID就会改变,这会导致因为serialVersionUID不一致而造成的反序列化失败。

public class Student implements Serializable {private static final long serialVersionUID = 2894055642774362458L;

    private transient String name;
    @Expose(serialize = false,deserialize = true)
    private int age;
    @SerializedName("goals")
    private Score score;
    public Student(){}

    public Student(String name, int age, Score score) {this.name = name;
        this.age = age;
        this.score = score;
    }

    public String getName() {return name;
    }

    public int getAge() {return age;
    }

    public Score getScore() {return score;
    }

    public void setName(String name) {this.name = name;
    }

    public void setAge(int age) {this.age = age;
    }

    public void setScore(Score score) {this.score = score;
    }

    @Override
    public String toString() {return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", score=" + score +
                '}';
    }
}
public class Score implements Serializable {private static final long serialVersionUID = -1947844853731260432L;
    private int math;
    private int english;
    private int chinese;

    public int getMath() {return math;
    }

    public void setMath(int math) {this.math = math;
    }

    public int getEnglish() {return english;
    }

    public void setEnglish(int english) {this.english = english;
    }

    public int getChinese() {return chinese;
    }

    public void setChinese(int chinese) {this.chinese = chinese;
    }

    public Score() {}

    public Score(int math, int english, int chinese) {this.math = math;
        this.english = english;
        this.chinese = chinese;
    }

    @Override
    public String toString() {return "Score{" +
                "math=" + math +
                ", english=" + english +
                ", chinese=" + chinese +
                '}';
    }
}
序列化

使用ObjectOutPutStream类实现对象的序列化。

  • 打开ObjectOutputStream流:new ObjectOutputStream(OutputStream output),安卓中可以使用openFileOutput(filepath)打开OutputStream流
  • writeObject(obj):obj是实现Serializable接口的实体类对象
  • 关闭流要
Student serialStudent = new Student("花",18,new Score(98,95,95));
ObjectOutputStream output = new ObjectOutputStream(openFileInput("student.txt"));
output.writeObject(obj);
output.close();
反序列化

使用ObjectOutPutStream类实现对象的序列化。

  • 打开ObjectInputStream流:new ObjectInputStream(InputStream input),安卓中可以使用openFileInput(filepath)打开InputStream流
  • readObject():把二进制的对象数据进行返序列化
  • 关闭流要
ObjectInputStream input = new ObjectInputStream(openFileInput("student.txt"));
Student serialStudent1 = (Student) input.readObject();
input.close();
完整实现
//Serializable test:生成的 文件是16进制类型的,如果想要看文件,可以在AS中安装插件进行查看

Student serialStudent = new Student("花",18,new Score(98,95,95));

try {ObjectOutputStream output = new ObjectOutputStream(openFileOutput("student.txt",MODE_PRIVATE));
    output.writeObject(serialStudent);
    output.flush();
    output.close();
    
    
    ObjectInputStream input = new ObjectInputStream(openFileInput("student.txt"));
    Student serialStudent1 = (Student) input.readObject();
    input.close();
    Log.i(TAG, "onCreate: Serializable_test"+serialStudent1.toString());

} catch (IOException | ClassNotFoundException e) {e.printStackTrace();
}
使用Parcelable

使用Parcelable方式进行序列化,需要让要序列化的对象implements Parcelable接口,创建,并且实现它内部的方法。

  • public static final Creator CREATOR = new Creator() {}:创建一个Creator对象,实现反序列化。
  • StudentP(Parcel in):完成反序列化的工作。
  • writeToParcel(Parcel dest, int flags):完成序列化的工作。
public class StudentP implements Parcelable {private String name;
    private int age;
    private ScoreP score;
    public StudentP(){}

    public StudentP(String name, int age, ScoreP score) {this.name = name;
        this.age = age;
        this.score = score;
    }

    protected StudentP(Parcel in) {name = in.readString();
        age = in.readInt();
    }

    public static final CreatorCREATOR = new Creator() {@Override
        public StudentP createFromParcel(Parcel in) {return new StudentP(in);
        }

        @Override
        public StudentP[] newArray(int size) {return new StudentP[size];
        }
    };

    public String getName() {return name;
    }

    public int getAge() {return age;
    }

    public ScoreP getScore() {return score;
    }

    public void setName(String name) {this.name = name;
    }

    public void setAge(int age) {this.age = age;
    }

    public void setScore(ScoreP score) {this.score = score;
    }

    @Override
    public int describeContents() {return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {dest.writeString(name);
        dest.writeInt(age);
    }

    @Override
    public String toString() {return "StudentP{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", score=" + score +
                '}';
    }
}
public class ScoreP implements Parcelable {private int math;
    private int english;
    private int chinese;

    protected ScoreP(Parcel in) {math = in.readInt();
        english = in.readInt();
        chinese = in.readInt();
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {dest.writeInt(math);
        dest.writeInt(english);
        dest.writeInt(chinese);
    }

    @Override
    public int describeContents() {return 0;
    }

    public static final CreatorCREATOR = new Creator() {@Override
        public ScoreP createFromParcel(Parcel in) {return new ScoreP(in);
        }

        @Override
        public ScoreP[] newArray(int size) {return new ScoreP[size];
        }
    };

    public int getMath() {return math;
    }

    public void setMath(int math) {this.math = math;
    }

    public int getEnglish() {return english;
    }

    public void setEnglish(int english) {this.english = english;
    }

    public int getChinese() {return chinese;
    }

    public void setChinese(int chinese) {this.chinese = chinese;
    }

    public ScoreP() {}

    public ScoreP(int math, int english, int chinese) {this.math = math;
        this.english = english;
        this.chinese = chinese;
    }

    @Override
    public String toString() {return "ScoreP{" +
                "math=" + math +
                ", english=" + english +
                ", chinese=" + chinese +
                '}';
    }
}
序列化
@Override
public void writeToParcel(Parcel dest, int flags) {dest.writeInt(math);
        dest.writeInt(english);
        dest.writeInt(chinese);
}
反序列化
protected ScoreP(Parcel in) {math = in.readInt();
        english = in.readInt();
        chinese = in.readInt();
 }

注意:

序列化和反序列化时的顺序必须一致。比如下面这几个属性的顺序是int,String,int类型的 ,那么它的序列化和反序列化就得按照顺序writeInt和readInt,如下:

//属性顺序 
		private int math;
   	private String name ;
    private int english;
    //序列化顺序
    public void writeToParcel(Parcel dest, int flags) {dest.writeInt(math);
        dest.writeString(name);
        dest.writeInt(chinese);
		}
		//反序列化顺序
     protected T(Parcel in) {math = in.readInt();
        english = in.readString();
        chinese = in.readInt();
 		}
   
完整实现

Parcelable是专门为Android定制的序列化方式,它不像Serializable方式那样频繁的操作IO,所以它的效率高很多。

//Parcelable test
Intent intent = new Intent(this , ParcelableActivity.class);
StudentP parcelableStudent = new StudentP("MAY", 17, new ScoreP(95, 90, 90));
Bundle bundle = new Bundle();
bundle.putParcelable("student",parcelableStudent);
intent.putExtra("student",bundle);
startActivity(intent);
使用Json

JSON(JavaScript Object Notation, JS对象简谱)是一种轻量级的数据交换格式。它的层次结构简洁清晰,是网络上传输数据很好用的一个手段。Json有几个很好用的库,FastJson和Gson,本文使用Gson。

编写和校验Json串
  • 编写:在AndroidStudio中:new ->ScratchFile
  • 校验:使用beJson网站:www.beJson.com
使用Gson

Gson地址:https://github.com/google/gson

  • 添加依赖Gson库
dependencies {
    implementation 'com.google.code.gson:gson:2.10'
    }
序列化

使用Gson的toJson(obj)方法.

  • 对象的序列化
//object
        Gson gson = new Gson();
        Student student = new Student("teresa_may",16,new Score(60,60,60));
        String stuJson = gson.toJson(student);
        Log.i(TAG, "onCreate: gson_stu:"+stuJson);
  • 数组的序列化
Student[] students = new Student[5];
        for (int i = 0;i<5;i++){Student s = new Student("teresa_may",16+i,new Score(60+i,60+i,60+i));
            students[i] = s;
        }
        String stus_Json = gson.toJson(students);
        Log.i(TAG, "onCreate: stu_array_json:"+stus_Json);
  • list/map/set的序列化
//list、map、set
        Liststu_list = new ArrayList(Arrays.asList(students));
        String stulist_Json = gson.toJson(stu_list);
        Log.i(TAG, "onCreate: stus_list_json:"+stus_Json);
反序列化

使用Gson的fromJson(json_str,Class)方法。

  • 对象的反序列化
Student student_f = gson.fromJson(stuJson,Student.class);
        Log.i(TAG, "onCreate: gson_from_json:"+student_f.toString());
  • 数组的反序列化
Student[] students_f = gson.fromJson(stus_Json,Student[].class);
        Log.i(TAG, "onCreate: students_from_json:"+students_f.toString());
  • list/map/set的反序列化

略有不同。需要使用Type对ArrayList的参数化类型进行明确才能进行反序列化。

Type type = new TypeToken>(){}.getType();
        ArrayListstudents_list = gson.fromJson(stulist_Json,type);
        Log.i(TAG, "onCreate: students_list from json:"+students_list.toString());
完整实现
   //Gson test
        //object
        Gson gson = new Gson();
        Student student = new Student("teresa_may",16,new Score(60,60,60));
        String stuJson = gson.toJson(student);
        Log.i(TAG, "onCreate: gson_stu:"+stuJson);
        Student student_f = gson.fromJson(stuJson,Student.class);
        Log.i(TAG, "onCreate: gson_from_json:"+student_f.toString());

        //array
        Student[] students = new Student[5];
        for (int i = 0;i<5;i++){Student s = new Student("teresa_may",16+i,new Score(60+i,60+i,60+i));
            students[i] = s;
        }
        String stus_Json = gson.toJson(students);
        Log.i(TAG, "onCreate: stu_array_json:"+stus_Json);
        Student[] students_f = gson.fromJson(stus_Json,Student[].class);
        Log.i(TAG, "onCreate: students_from_json:"+students_f.toString());

        //list、map、set
        Liststu_list = new ArrayList(Arrays.asList(students));
        String stulist_Json = gson.toJson(stu_list);
        Log.i(TAG, "onCreate: stus_list_json:"+stus_Json);

        Type type = new TypeToken>(){}.getType();
        ArrayListstudents_list = gson.fromJson(stulist_Json,type);
        Log.i(TAG, "onCreate: students_list from json:"+students_list.toString());
控制序列化和反序列化 @Serialization

用于属性上表示该属性在json中的key值,如果不使用这个注解,那么在序列化和反序列化的时候使用属性的名字作为key。有时候json串中的key存在java中的关键字时,可以使用这个注解为当前属性和json串中的key进行映射。

@SreializedName("class")
private String cls;

json中的样子:
{"class":"Student.class"}
@Expose

@Expose控制对象的序列化和反序列化,有两个属性:serializedeserialize,默认值为true,表示允许序列化和反序列化。

@Expose(serialize = false,deserialize = true)//字段不参与序列化,允许反序列化
static关键字

static关键字修饰的字段不会被序列化,反序列化时内部的值是该字段类型的默认值。

transient关键字

static关键字修饰的字段不会被序列化和反序列化

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


分享名称:对象的序列化与反序列化-创新互联
地址分享:http://pwwzsj.com/article/ddssed.html