精华内容
下载资源
问答
  • 在我们的C++中 通过ofstream ifstream 对象 读写文件更加的方便了。对二进制文件的读写 主要使用ofstream::write,ifstream::read函数。如果对文件读写方向感不强,记不住的 ,记住4个字就行了。读入写出。这个4...

    相关函数介绍

    在我们的C语言中读写二进制文件一般使用的fread、fwrite全局函数,当然也可以使用更底层的read和write函数。在我们的C++中 通过ofstream 和 ifstream 对象 读写文件更加的方便了。对二进制文件的读写 主要使用 ofstream::write,ifstream::read函数。如果对文件读写方向感不强,记不住的 ,记住4个字就行了。读入写出。这个4个字是针对 程序或者说是内存!往内存里面读数据 -> read ,往磁盘里面写数据->write。这样永远就会忘了。还有一些其他的函数,都比较简单。感觉用起来很方便。

    这里普及下序列化和反序列化

    序列化: 将数据结构或对象转换成二进制串的过程。
    反序列化:将在序列化过程中所生成的二进制串转换成数据结构或者对象的过程。

    下面就用相关函数实现普通的字符文件操作 和 二进制文件操作。代码注释很详细

    普通文件操作

    #define _CRT_SECURE_NO_WARNINGS
    #include <iostream>
    #include <fstream>
    using namespace std;
    
    //写文件
    void WriteFile()
    {
    	ofstream file("./text.txt",ios::out);
    	if (!file.is_open())
    	{
    		cout << "文件打开失败" << endl;
    		return;
    	}
    	file << "姓名:laymond" << endl;
    	file << "年龄:18" << endl;
    	file.close();
    	return;
    }
    //读文件
    void ReadFile()
    {
    	ifstream file("./text.txt", ios::in);
    	if (!file.is_open())
    	{
    		cout << "文件打开失败" << endl;
    		return;
    	}
    	char temp[1024] = { 0 };
    	//读取文件3种方式
    	//1、read  file.eof() 作为判断条件 会慢一拍
    	while (file >> temp)
    	//while (!file.eof())
    	{
    		//file.read(temp, 1024); //这样会读取到\n
    		//cout << temp
    
    		// >>按行读取,不会读换行符
    		cout << temp << endl;
    	}
    
    	//2、get 一个一个字符的读取
    	//char c;
    	//while ( (c=file.get()) != EOF )
    	//{
    	//	cout << c;
    	//}
    	
    	//3、一行一样读取 getline 会把\n 舍弃掉....
    	//while (file.getline(temp,1024))
    	//{
    	//	cout << temp << endl;
    	//}
    	file.close();
    }

     

    二进制文件操作(序列化和反序列化)

     

    接上面代码哈,是写在同一个文件中的。

    class Person
    {
    public:
    	Person(char* name, int age)
    	{
    		strcpy(this->name, name);
    		this->age = age;
    	}
    	void showInfo()
    	{
    		cout << name << " " << age << endl;
    	}
    public:
    	char name[10]{ 0 };
    	int age = 0;
    };
    //二进制文件 进行写
    void WriteBinaryFile()
    {
    	ofstream file("./binary.txt",ios::out | ios::binary );
    	if (!file.is_open())
    	{
    		cout << "文件打开失败" << endl;
    	}
    	Person p1("Lay1", 11);
    	Person p2("Lay2", 2);
    	Person p3("Lay3", 151);
    	Person p4("Lay4", 5);
    	Person p5("Lay5", 9);
    	file.write((char*)&p1, sizeof(p1));
    	file.write((char*)&p2, sizeof(p2));
    	file.write((char*)&p3, sizeof(p3));
    	file.write((char*)&p4, sizeof(p4));
    	file.write((char*)&p5, sizeof(p5));
    
    	file.close();
    }
    //二进制文件 进行读
    void ReadBinaryFile()
    {
    	ifstream file("./binary.txt", ios::in | ios::binary);
    	if (!file.is_open())
    	{
    		cout << "文件打开失败" << endl;
    	}
    	//开辟一块空间 存放读取的数据
    	char* temp = new char[sizeof(Person)];
    	//或者 Person p;开辟的空间肯定合适
    
    	//将数据读入的 temp对应的空间
    	while (file.read(temp,sizeof(Person)))
    	{
    		Person p = *(Person*)(temp);
    		p.showInfo();
    	}
    	file.close();
    }
    
    int main(int argc, char *argv[])
    {
    	//读写 字符文件
    	//WriteFile();
    	//ReadFile();
    
    	//读写 二进制文件
    	//WriteBinaryFile();
    	ReadBinaryFile();
    
    	return EXIT_SUCCESS;
    }

    运行结果验证

    展开全文
  • 实现了用三种序列化方式(binary,soap,xml)序列化对象,其中Student对象中还包含图片(用binarysoap),School中没有图片(用XML)。
  • Java 序列化反序列化

    千次阅读 2020-09-05 13:04:20
    介绍 Java 的序列化反序列化

    Java 序列化与反序列化


    1 序列化与反序列化的概念

    • Java 序列化是指:将对象转化成一个字节序列(二进制数据)的过程。

    • 将序列化对象写入文件之后,可以从文件中读取出来,并且对它进行反序列化。

    • Java 反序列化是指:将一个对象的字节序列恢复成 Java 对象的过程。

    • 一个平台中序列化的对象,可以在另一个平台中进行反序列化,因为这个过程是在 JVM 中独立完成的,可以依赖于 Java 的可移植性。


    2 核心类与关键字总览

    • ObjectOutputStream:IO 类,包含序列化对象的方法,writeObject()

    • ObjectInputStream:IO 类,包含反序列化对象的方法,readObject()

    • 上面两个 IO 流类是高层次的数据库,需要借助文件流进行序列化与反序列化操作。

    • Serializable ,接口,是一个标志性接口,标识可以在 JVM 中进行序列化,JVM 会为该类自动生成一个序列化版本号。参与序列化与反序列化的类必须实现 Serializable 接口。

    • serialVersionUID,类属性,序列化版本号,用于给 JVM 区别同名类,没有提供版本号,JVM会默认提供序列化版本号。

    • transient,关键字,当序列化时,不希望某些属性参与,则可以使用这个关键字标注该属性。


    3 序列化与反序列化的过程

    • 内存中的数据信息被拆分成一小块一小块的部分,为每个小块设置编号,然后存放到硬盘文件中,也就是将 Java 对象对象的状态保存下来存储到文件中的过程就叫做序列化。

    • 将硬盘中保存了 Java 对象状态的字节序列按照编号组装成对象恢复到内存中,这个过程称为反序列化。


    3 应用示例

    参与序列化和反序列化的 Java 类

    public class Student implements Serializable {
        private String name;
        private int age;
        //  以下省略有参构造、无参构造、set、get、toString
    }
    
    • 参与序列化和反序列化的类必须实现 Serializable 接口。

    序列化操作

    public static void main(String[] args) throws Exception {
        //  创建 Java 对象
        Student student = new Student("张三",22);
        //  对象输出流
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("student"));
        // 使用 writeObject 序列化对象
        oos.writeObject(student);
        // 刷新
        oos.flush();
        //  关闭流
        oos.close();
    }
    
    • 序列化后的二进制文件会被保存到文件输出流指定的路径。

    反序列化操作

    public static void main(String[] args) throws Exception {
        //  对象输入流
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("student"));
        //  使用 readObject() 反序列化  
        Object obj = ois.readObject();
        //  使用对象
        System.out.println(obj);
        //  关闭流
        ois.close();
    }
    
    • 反序列化需要借助文件输入流读取指定路径的二进制文件。

    4 序列化版本号的作用 serialVersionUID

    • JVM 首先会通过类名来区分 Java 类,类名不同,则不是同一个类。当类名相同时,JVM 就会通过序列化版本号来区分 Java 类,如果序列化版本号相同就为同一个类,序列化版本号不同就为不同的类。

    • 在序列化一个对象时,如果没有指定序列化版本号,后期对该类的源码进行修改并重新编译后,会导致修改前后的序列化版本号不一致,因为 JVM 会提供一个新的序列化版本号给该类对象。

    • 此时再用以往的反序列化代码去反序列化该类的对象,就会抛出异常 java.io.InvalidClassException ,所以序列化一个类时最好指定一个序列化版本号,或者永远不修改此类。

    public class Student implements Serializable {
        private static final Long serialVersionUID = 1L;
    }
    
    • 由 JVM 提供序列化版本号的好处是,同名却不同功能的类,会有两个不同的序列化版本号,JVM 可以通过序列化版本号加以区分,缺点是一旦修改源码,会重新提供序列化版本号,导致修改前后的序列化版本号不一致,进行反序列化时会出现运行出现异常。

    • 由 开发人员 手动提供序列化版本号的好处是,当修改了被序列化类的源码后,以往写的反序列化代码依然可以使用,如 JDK 中的 String 类。以便后期进行增强和维护不会影响使用。

    在这里插入图片描述


    5 transient 关键字

    • 这个关键字表示游离的,不参与序列化的。

    • 在序列化一个对象时,如果不希望某个属性参加序列化,可以使用 transient 修饰该属性。

    • 被该关键字修饰的属性不会参与到序列化中。

    public class Student implements Serializable {
    
        private static final Long serialVersionUID = 1L;
    
        private String name;
        private transient int age;
    }
    
    • 如上类,在序列化时就不会保存 age 属性,在反序列化时就不能会付出该属性,默认恢复成 null 或 0 ,由属性类型决定。

    6 序列化的好处及应用场景

    • 序列化会将内存中对象的状态转换成二进制文件保存到磁盘当中,当再次使用时会从磁盘中读取该二进制文件,将 Java 对象的状态恢复到内存中。

    • 当你想把内存中的对象保存到磁盘文件或数据库中时可以使用序列化。

    • 当你想在网络传输中传送 Java 对象时,可以使用序列化。

    • 当你想通过 RMI 传输对象时,可以使用序列化。


    7 序列化注意事项

    • 序列化只会保存对象的属性状态,不会保存对象中的方法。

    • 父类实现了 Serializable 接口,则其子类也自动实例化了该接口,也就是说子类不用显式实现 Serializable 接口也能参与序列化和反序列化。

    • 一个对象 A 的实例变量引用了其他对象 B,在 A 对象实例化的过程中 ,也会序列化 B ,前提是 A、B 两个类都实现了 Serializable 接口。

    • 当一个类实现 Serializable 接口时,最好手动指定一个序列化版本号(serialVersionUID),避免修改源代码后导致反序列化出现异常。

    • 当一个类对象会被多次重复使用,且一般不会对其属性做修改,就可以对其进行序列化。例如数据库操作中的实体类。


    参考博文:

    展开全文
  • 序列化反序列化之ParcelableSerializable浅析

    万次阅读 多人点赞 2016-09-26 15:50:41
    转载请注明出处(万分感谢!...  在日常的应用开发中,我们可能需要让某些对象离开内存空间,存储到物理磁盘,以便长期保存,同时也能减少对内存的压力,而在需要时再将其从磁盘读取到内存,比如将某个特

    转载请注明出处(万分感谢!):
    http://blog.csdn.net/javazejian/article/details/52665164
    出自【zejian的博客】

    本篇小部分内容摘自android开发艺术探索

      在日常的应用开发中,我们可能需要让某些对象离开内存空间,存储到物理磁盘,以便长期保存,同时也能减少对内存的压力,而在需要时再将其从磁盘读取到内存,比如将某个特定的对象保存到文件中,隔一段时间后再把它读取到内存中使用,那么该对象就需要实现序列化操作,在java中可以使用Serializable接口实现对象的序列化,而在android中既可以使用Serializable接口实现对象序列化也可以使用Parcelable接口实现对象序列化,但是在内存操作时更倾向于实现Parcelable接口,这样会使用传输效率更高效。接下来我们将分别详细地介绍这样两种序列化操作~~~~。

    序列化与反序列

    首先来了解一下序列化与反序列化。

    • 序列化

      由于存在于内存中的对象都是暂时的,无法长期驻存,为了把对象的状态保持下来,这时需要把对象写入到磁盘或者其他介质中,这个过程就叫做序列化。

    • 反序列化

      反序列化恰恰是序列化的反向操作,也就是说,把已存在在磁盘或者其他介质中的对象,反序列化(读取)到内存中,以便后续操作,而这个过程就叫做反序列化。

      概括性来说序列化是指将对象实例的状态存储到存储媒体(磁盘或者其他介质)的过程。在此过程中,先将对象的公共字段和私有字段以及类的名称(包括类所在的程序集)转换为字节流,然后再把字节流写入数据流。在随后对对象进行反序列化时,将创建出与原对象完全相同的副本。

    • 实现序列化的必要条件

      一个对象要实现序列化操作,该类就必须实现了Serializable接口或者Parcelable接口,其中Serializable接口是在java中的序列化抽象类,而Parcelable接口则是android中特有的序列化接口,在某些情况下,Parcelable接口实现的序列化更为高效,关于它们的实现案例我们后续会分析,这里只要清楚知道实现序列化操作时必须实现Serializable接口或者Parcelable接口之一即可。

    • 序列化的应用情景

      主要有以下情况(但不限于以下情况)

    • 1)内存中的对象写入到硬盘;
    • 2)用套接字在网络上传送对象;
    • 3)通过RMI(Remote Method Invoke 远程方法调用)传输对象;

      接下来我们分别介绍两种序列化的实现方式

    Serializable

      Serializable是java提供的一个序列化接口,它是一个空接口,专门为对象提供标准的序列化和反序列化操作,使用Serializable实现类的序列化比较简单,只要在类声明中实现Serializable接口即可,同时强烈建议声明序列化标识。如下:

    package com.zejian.ipctest;
    
    import java.io.Serializable;
    
    /**
     * Created by zejian
     * Time 2016/9/25.
     * Description:
     */
    public class Client implements Serializable{
    
        /**
         * 生成序列号标识
         */
        private static final long serialVersionUID = -2083503801443301445L;
    
        private int id;
        private String name;
    
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    }

      如上述代码所示,Client类实现的Serializable接口并声明了序列化标识serialVersionUID,该ID由编辑器生成,当然也可以自定义,如1L,5L,不过还是建议使用编辑器生成唯一标识符。那么serialVersionUID有什么作用呢?实际上我们不声明serialVersionUID也是可以的,因为在序列化过程中会自动生成一个serialVersionUID来标识序列化对象。既然如此,那我们还需不需要要指定呢?由于serialVersionUID是用来辅助序列化和反序列化过程的,原则上序列化后的对象中serialVersionUID只有和当前类的serialVersionUID相同才能够正常被反序列化,也就是说序列化与反序列化的serialVersionUID必须相同才能够使序列化操作成功。具体过程是这样的:序列化操作的时候系统会把当前类的serialVersionUID写入到序列化文件中,当反序列化时系统会去检测文件中的serialVersionUID,判断它是否与当前类的serialVersionUID一致,如果一致就说明序列化类的版本与当前类版本是一样的,可以反序列化成功,否则失败。报出如下UID错误:

    Exception in thread "main" java.io.InvalidClassException: com.zejian.test.Client; 
    local class incompatible: stream classdesc serialVersionUID = -2083503801443301445, 
    local class serialVersionUID = -4083503801443301445

      因此强烈建议指定serialVersionUID,这样的话即使微小的变化也不会导致crash的出现,如果不指定的话只要这个文件多一个空格,系统自动生成的UID就会截然不同的,反序列化也就会失败。ok~,了解这么多,下面来看一个如何进行对象序列化和反序列化的列子:

    package com.zejian.ipctest;
    
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    
    /**
     * Created by zejian
     * Time 2016/9/25.
     * Description:
     */
    public class Stest {
    
        public static void main(String[] args) throws Exception {
    
            //把对象序列化到文件
            Client client = new Client();
            client.setId(000001);
            client.setName("client");
    
            ObjectOutputStream oo = new ObjectOutputStream
                    (new FileOutputStream("/Users/zejian/Desktop/cache.txt"));
            oo.writeObject(client);
            oo.close();
    
            //反序列化到内存
            ObjectInputStream oi = new ObjectInputStream
                (new FileInputStream("/Users/zejian/Desktop/cache.txt"));
            Client c_back = (Client) oi.readObject();
            System.out.println("Hi, My name is " + c_back.getName());
            oi.close();
    
        }
    }

      从代码可以看出只需要ObjectOutputStream和ObjectInputStream就可以实现对象的序列化和反序列化操作,通过流对象把client对象写到文件中,并在需要时恢复c_back对象,但是两者并不是同一个对象了,反序列化后的对象是新创建的。这里有两点特别注意的是如果反序列类的成员变量的类型或者类名,发生了变化,那么即使serialVersionUID相同也无法正常反序列化成功。其次是静态成员变量属于类不属于对象,不会参与序列化过程,使用transient关键字标记的成员变量也不参与序列化过程。
      关键字transient,这里简单说明一下,Java的serialization提供了一种持久化对象实例的机制。当持久化对象时,可能有一个特殊的对象数据成员,我们不想用serialization机制来保存它。为了在一个特定对象的一个域上关闭serialization,可以在这个域前加上关键字transient。当一个对象被序列化的时候,transient型变量的值不包括在序列化的表示中,然而非transient型的变量是被包括进去的。
      另外,系统的默认序列化过程是可以改变的,通过实现如下4个方法,即可以控制系统的默认序列化和反序列过程:

    package com.zejian.ipctest;
    
    import java.io.IOException;
    import java.io.ObjectStreamException;
    import java.io.Serializable;
    
    /**
     * Created by zejian
     * Time 2016/9/25.
     * Description:
     */
    public class Client implements Serializable{
    
        /**
         * 生成序列号标识
         */
        private static final long serialVersionUID = -4083503801443301445L;
    
    
        private int id;
        private String name;
    
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
    
        /**
         * 序列化时,
         * 首先系统会先调用writeReplace方法,在这个阶段,
         * 可以进行自己操作,将需要进行序列化的对象换成我们指定的对象.
         * 一般很少重写该方法
         * @return
         * @throws ObjectStreamException
         */
        private Object writeReplace() throws ObjectStreamException {
            System.out.println("writeReplace invoked");
            return this;
        }
        /**
         *接着系统将调用writeObject方法,
         * 来将对象中的属性一个个进行序列化,
         * 我们可以在这个方法中控制住哪些属性需要序列化.
         * 这里只序列化name属性
         * @param out
         * @throws IOException
         */
        private void writeObject(java.io.ObjectOutputStream out) throws IOException {
            System.out.println("writeObject invoked");
            out.writeObject(this.name == null ? "zejian" : this.name);
        }
    
        /**
         * 反序列化时,系统会调用readObject方法,将我们刚刚在writeObject方法序列化好的属性,
         * 反序列化回来.然后通过readResolve方法,我们也可以指定系统返回给我们特定的对象
         * 可以不是writeReplace序列化时的对象,可以指定其他对象.
         * @param in
         * @throws IOException
         * @throws ClassNotFoundException
         */
        private void readObject(java.io.ObjectInputStream in) throws IOException,
                ClassNotFoundException {
            System.out.println("readObject invoked");
            this.name = (String) in.readObject();
            System.out.println("got name:" + name);
        }
    
    
        /**
         * 通过readResolve方法,我们也可以指定系统返回给我们特定的对象
         * 可以不是writeReplace序列化时的对象,可以指定其他对象.
         * 一般很少重写该方法
         * @return
         * @throws ObjectStreamException
         */
        private Object readResolve() throws ObjectStreamException {
            System.out.println("readResolve invoked");
            return this;
        }
    }

      通过上面的4个方法,我们就可以随意控制序列化的过程了,由于在大部分情况下我们都没必要重写这4个方法,因此这里我们也不过介绍了,只要知道有这么一回事就行。ok~,对于Serializable的介绍就先到这里。

    Parcelable

      鉴于Serializable在内存序列化上开销比较大,而内存资源属于android系统中的稀有资源(android系统分配给每个应用的内存开销都是有限的),为此android中提供了Parcelable接口来实现序列化操作,Parcelable的性能比Serializable好,在内存开销方面较小,所以在内存间数据传输时推荐使用Parcelable,如通过Intent在activity间传输数据,而Parcelable的缺点就使用起来比较麻烦,下面给出一个Parcelable接口的实现案例,大家感受一下:

    package com.zejian.ipctest;
    import android.os.Parcel;
    import android.os.Parcelable;
    
    /**
     * Created by zejian
     * Time 2016/9/25.
     * Description:
     */
    public class NewClient implements Parcelable {
    
        public int id;
        public String name;
        public User user;
    
        /**
         * 当前对象的内容描述,一般返回0即可
         * @return
         */
        @Override
        public int describeContents() {
            return 0;
        }
    
        /**
         * 将当前对象写入序列化结构中
         * @param dest
         * @param flags
         */
        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeInt(this.id);
            dest.writeString(this.name);
            dest.writeParcelable(this.user,0);
        }
    
        public NewClient() {
        }
    
        /**
         * 从序列化后的对象中创建原始对象
         * @param in
         */
        protected NewClient(Parcel in) {
            this.id = in.readInt();
            this.name = in.readString();
           //User是另一个序列化对象,此方法序列需要传递当前线程的上下文类加载器,否则会报无法找到类的错误
           this.user=in.readParcelable(Thread.currentThread().getContextClassLoader());
        }
    
        /**
         * public static final一个都不能少,内部对象CREATOR的名称也不能改变,必须全部大写。
         * 重写接口中的两个方法:
         * createFromParcel(Parcel in) 实现从Parcel容器中读取传递数据值,封装成Parcelable对象返回逻辑层,
         * newArray(int size) 创建一个类型为T,长度为size的数组,供外部类反序列化本类数组使用。
         */
        public static final Parcelable.Creator<NewClient> CREATOR = new Parcelable.Creator<NewClient>() {
            /**
             * 从序列化后的对象中创建原始对象
             */
            @Override
            public NewClient createFromParcel(Parcel source) {
                return new NewClient(source);
            }
    
            /**
             * 创建指定长度的原始对象数组
             * @param size
             * @return
             */
            @Override
            public NewClient[] newArray(int size) {
                return new NewClient[size];
            }
        };
    }

      从代码可知,在序列化的过程中需要实现的功能有序列化和反序列以及内容描述。其中writeToParcel方法实现序列化功能,其内部是通过Parcel的一系列write方法来完成的,接着通过CREATOR内部对象来实现反序列化,其内部通过createFromParcel方法来创建序列化对象并通过newArray方法创建数组,最终利用Parcel的一系列read方法完成反序列化,最后由describeContents完成内容描述功能,该方法一般返回0,仅当对象中存在文件描述符时返回1。同时由于User是另一个序列化对象,因此在反序列化方法中需要传递当前线程的上下文类加载器,否则会报无法找到类的错误。
      简单用一句话概括来说就是通过writeToParcel将我们的对象映射成Parcel对象,再通过createFromParcel将Parcel对象映射成我们的对象。也可以将Parcel看成是一个类似Serliazable的读写流,通过writeToParcel把对象写到流里面,在通过createFromParcel从流里读取对象,这个过程需要我们自己来实现并且写的顺序和读的顺序必须一致。ok~,到此Parcelable接口的序列化实现基本介绍完。
      那么在哪里会使用到Parcelable对象呢?其实通过Intent传递复杂类型(如自定义引用类型数据)的数据时就需要使用Parcelable对象,如下是日常应用中Intent关于Parcelable对象的一些操作方法,引用类型必须实现Parcelable接口才能通过Intent传递,而基本数据类型,String类型则可直接通过Intent传递而且Intent本身也实现了Parcelable接口,所以可以轻松地在组件间进行传输。

    方法名称含义
    putExtra(String name, Parcelable value)设置自定义类型并实现Parcelable的对象
    putExtra(String name, Parcelable[] value)设置自定义类型并实现Parcelable的对象数组
    public Intent putParcelableArrayListExtra(String name, ArrayList value)设置List数组,其元素必须是实现了Parcelable接口的数据

      除了以上的Intent外系统还为我们提供了其他实现Parcelable接口的类,再如Bundle、Bitmap,它们都是可以直接序列化的,因此我们可以方便地使用它们在组件间进行数据传递,当然Bundle本身也是一个类似键值对的容器,也可存储Parcelable实现类,其API方法跟Intent基本相似,由于这些属于android基础知识点,这里我们就不过多介绍了。

    Parcelable 与 Serializable 区别

    • 两者的实现差异
        Serializable的实现,只需要实现Serializable接口即可。这只是给对象打了一个标记(UID),系统会自动将其序列化。而Parcelabel的实现,不仅需要实现Parcelabel接口,还需要在类中添加一个静态成员变量CREATOR,这个变量需要实现 Parcelable.Creator 接口,并实现读写的抽象方法。

    • 两者的设计初衷
        Serializable的设计初衷是为了序列化对象到本地文件、数据库、网络流、RMI以便数据传输,当然这种传输可以是程序内的也可以是两个程序间的。而Android的Parcelable的设计初衷是由于Serializable效率过低,消耗大,而android中数据传递主要是在内存环境中(内存属于android中的稀有资源),因此Parcelable的出现为了满足数据在内存中低开销而且高效地传递问题。

    • 两者效率选择
        Parcelable的性能比Serializable好,在内存开销方面较小,所以Android应用程序在内存间数据传输时推荐使用Parcelable,如activity间传输数据和AIDL数据传递,而Serializable将数据持久化的操作方便,因此在将对象序列化到存储设置中或将对象序列化后通过网络传输时建议选择Serializable(Parcelable也是可以,只不过实现和操作过程过于麻烦并且为了防止android版本不同而导致Parcelable可能不同的情况,因此在序列化到存储设备或者网络传输方面还是尽量选择Serializable接口)。

    • 两者需要注意的共同点
        无论是Parcelable还是Serializable,执行反序列操作后的对象都是新创建的,与原来的对象并不相同,只不过内容一样罢了。

    Android studio 中的快捷生成方式

    • Android studio 快捷生成Parcelable代码

      在程序开发过程中,我们实现Parcelable接口的代码都是类似的,如果我们每次实现一个Parcelable接口类,就得去编写一次重复的代码,这显然是不可取的,不过幸运的是,android studio 提供了自动实现Parcelable接口的方法的插件,相当实现,我们只需要打开Setting,找到plugin插件,然后搜索Parcelable插件,最后找到android Parcelable code generator 安装即可:
    这里写图片描述

    重启android studio后,我们创建一个User类,如下:

    这里写图片描述

    然后使用刚刚安装的插件协助我们生成实现Parcelable接口的代码,window快捷键:Alt+Insert,Mac快捷键:cmd+n,如下:

    这里写图片描述

    最后结果如下:

    这里写图片描述

    • Android studio 快捷生成Serializable的UID
        在正常情况下,AS是默认关闭serialVersionUID生成提示的,我们需要打开setting,找到检测(Inspections选项),开启 Serializable class without serialVersionUID 检测即可,如下:

    这里写图片描述

    然后新建User类实现Serializable接口,右侧会提示添加serialVersionUID,如下:

    这里写图片描述

    最后在类名上,Alt+Enter(Mac:cmd+Enter),快捷代码提示,生成serialVersionUID即可:

    这里写图片描述

    最终结果如下:
    这里写图片描述

    ok~,以上便是Parcelable与Serializable接口的全部内容,本篇结束。

    展开全文
  • 对象序列化反序列化

    千次阅读 2018-05-14 19:40:28
    (1)对象序列化就是将Object装换成byte序列,反之叫对象反序列化。(2)序列化流(objectOutputStream),是字节过滤流,主要方法是writeobject()方法;反序列化流(objectInputStream),主要方法是readObject()...

    (1)对象的序列化就是将Object装换成byte序列,反之叫对象的反序列化。

    (2)序列化流(objectOutputStream),是字节过滤流,主要方法是writeobject()方法;反序列化流(objectInputStream),主要方法是readObject()方法。

    (3)序列化接口(serializable): 对象必须实现序列化接口,才能进行序列化,否则将会出现异常。这个接口,没有任何方法,只是一个标准。

    (4)用transient关键字标记的成员变量不参与序列化过程

    (5)序列化中子类和父类构造函数的调用问题

           1)一个类实现了序列化接口,那么其子类都可以进行序列化;

           2)对子类对象进行反序列化操作时,如果其父类没有实现序列化接口,那么其父类的构造函数会被调用。如果父类实现了序列化接口,那么其父类的构造函数不会被调用。

    (6)下面这个是对象序列化和反序列化的一个简单例子,以及使用transient关键字的实验代码,也可以将transient关键字去掉运行进行对比查看

    import java.io.Serializable;
    public class SeriaStudent implements Serializable{
    private String stuno;
    private String stuname;
    private transient int stuage;//该元素不会进行虚拟机默认的序列化,也可以自己完成这个元素的序列化

    public SeriaStudent(){
    }

    public SeriaStudent(String stuno, String stuname, int stuage) {
    super();
    this.stuno = stuno;
    this.stuname = stuname;
    this.stuage = stuage;
    }

     public String getStuno() {
    return stuno;
    }

    public void setStuno(String stuno) {
    this.stuno = stuno;
    }

    public String getStuname() {
    return stuname;
    }

    public void setStuname(String stuname) {
    this.stuname = stuname;
    }

    public int getStuage() {
    return stuage;
    }

    public void setStuage(int stuage) {
    this.stuage = stuage;
    }

    @Override
    public String toString() {
    return "ListStudent [stuno=" + stuno + ", stuname=" + stuname + ", stuage=" + stuage + "]";
    }

    //可以使用下面这两个方法自己完成被transient修饰的对象的序列化

    /*private void writeObject(java.io.ObjectOutputStream s)throws java.io.IOException{

    s.defaultWriteObject();//把虚拟机能默认的序列化的元素进行序列化操作
    s.writeInt(stuage);    //自己完成stuage的序列化
    }
        private void readObject(java.io.ObjectInputStream s)throws java.io.IOException,ClassNotFoundException{
        s.defaultReadObject(); //把虚拟机能默认反序列化的元素进行反序列化操作
        this.stuage=s.readInt();//自己完成stuage的反序列化操作
    }*/

    }

    以下程序先运行序列化程序,再将序列化程序注释后运行反序列化程序。

    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;


    public class ObjectSeriaDemo {

    public static void main(String[] args) throws Exception {
    String file="demo/obj.dat";
    //1.对象的序列化
    /*ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream(file));
    SeriaStudent stu=new SeriaStudent("1001","张三",20);
    oos.writeObject(stu);
    oos.flush();
    oos.close();*/
    //2.对象的反序列化
           ObjectInputStream ois=new ObjectInputStream(new FileInputStream(file));
    SeriaStudent stu=(SeriaStudent)ois.readObject();//强制类型转化
    System.out.println(stu);
    ois.close();
    }
    }

    age成员变量没有transient修饰时的运行结果


    age成员变量有transient修饰时的运行结果


    age成员变量有transient修饰,但是有

        private void writeObject(java.io.ObjectOutputStream s)throws java.io.IOException{

             }

        private void readObject(java.io.ObjectInputStream s)throws java.io.IOException,ClassNotFoundException{

    }

    这两个方法的运行结果



















































    展开全文
  • java序列化和反序列化以及序列化ID的作用分析

    万次阅读 多人点赞 2017-08-07 20:26:07
    java序列化和反序列化以及序列化ID的作用分析
  • Java对象序列化(Serialization)和反序列化详解

    万次阅读 多人点赞 2018-02-13 15:56:02
    1.序列化和反序列化 序列化(Serialization)是将对象的状态信息转化为可以存储或者传输的形式的过程,一般将一个对象...2.Java对象序列化和反序列化 在Java中,我们可以通过多种方式来创建对象,并且只要对象...
  • js对象序列化和反序列化

    千次阅读 2015-12-03 11:49:20
    序列化对象】  o = {x:1, y:{z:[false,null,""]}}; //定义一个测试对象  s = JSON.stringify(o); //s 是 '{"x":1,"y":{"z":[false,null,""]}}' ...函数、RegExp、Error对象和undefined值不能序列化和还原。
  • c++ 序列化和反序列化

    千次阅读 2019-09-19 15:36:35
    C++对象序列化的四种方法Google Protocol Buffers(protobuf)Boost.SerializationMFC SerializationNet Framework简单总结举例说明 什么是序列化? 序列化指的是将一个内存对象转化成一串字节数据(存储在一个字节...
  • c#对象序列化序列化实例c#对象序列化序列化实例c#对象序列化序列化实例c#对象序列化序列化实例c#对象序列化序列化实例c#对象序列化序列化实例
  • 一.认识FastJson fastjson是目前java语言中最快的json库,比自称最快的jackson速度要快...FastJson是一个Json处理工具包,包括“序列化反序列化”两部分,Fastjson是一个Java语言编写的高性能功能完善的JSON库。 F
  • C++ JSON 序列化反序列化

    热门讨论 2013-06-22 14:23:31
    C++ JSON 序列化反序列化 相关的博客文章见:http://blog.csdn.net/TragicGuy
  • 因此可以通过序列化储存java对象,再通过反序列化得到对象。 新建一个maven项目,添加相关的Jar包依赖。 <dependencies> <!-- https://mvnrepository.com/artifact/redis.clients/jedis --> ...
  • 遇到这个 Java Serializable 序列化这个接口,我们可能会有如下的问题a,什么叫序列化和反序列化 b,作用。为啥要实现这个 Serializable 接口,也就是为啥要序列化 c,serialVersionUID 这个的值到底是在怎么设置的...
  • SpringBoot的序列化和反序列化

    千次阅读 2020-11-11 15:06:16
    2、为什么要实现对象序列化和反序列化? (1)我们创建的Java对象被存储在Java堆中,当程序运行结束后,这些对象会被JVM回收。但在现实的应用中,可能会要求在程序运行结束之后还能读取这些对象,并在以后检索数据...
  • Java对象网络传输常用于Java异构平台间数据的交互,SocketHTTP均可以实现Java对象的网络传输,具体示例如下: 1、Socket实现Java对象的网络传输: keeper Java工程: UserInfo类: package com.jd.vo; ...
  • 序列化和反序列化的底层实现原理是什么?

    万次阅读 多人点赞 2018-04-07 13:53:41
    序列化和反序列化作为Java里一个较为基础的知识点,大家心里也有那么几句要说的,但我相信很多小伙伴掌握的也就是那么几句而已,如果再深究问一下Java如何实现序列化和反序列化的,就可能不知所措了!遥记当年也被问...
  • 最近使用RabbitMq发送消息时,遇到了提供者发送的消息(使用fastjson序列化数据对象)在消费者端转成(使用fastjson反序列化)数据对象后,属性缺失了 发送的消息对象: /** * 课本 **/ @Data public class ...
  • 对象序列化:就是将对象保存到磁盘中,或者在...要实现序列化与序列化,就要使用对象序列化对象序列化流: 对象序列化流:ObjectOutputStream 对象序列化流:ObjectInputStream 对象序列化流:ObjectOu.
  • 嵌套对象序列化我们希望通过实际的例子来阐述功能,因此让我们来扩展我们的UserSimple模型。在之前的发布中,user模型仅仅有一些基本的Java类型:public class UserSimple { String name; String email; boo
  • Qt序列化和反序列化

    千次阅读 2019-05-15 15:10:42
    定义: ...Qt中实现对象序列化的类是QDataStream,写二进制到流中 QFile file("file.dat"); //创建一个文档 file.open(QIODevice::WriteOnly);//打开并只写 QDataStream out(&file); //序列...
  • 这是一个用C#写的Socket服务器客户端,当然Socket服务器客户端不是主要的(有兴趣的朋友可以参考下),主要的内容是介绍如何通过这种Socket方式发送Object对象。 作者博客 http://luyugao.com
  • 序列化和反序列化是Java中最基础的知识点,也是很容易被大家遗忘的,虽然天天使用它,但并不一定都能清楚的说明白。我相信很多小伙伴们掌握的也就几句概念、关键字(Serializable)而已,如果深究问一下序列化和反序列...
  • C++实现二叉树的序列化和反序列化

    千次阅读 2019-07-06 10:45:45
    二叉树的序列化和反序列化 2. 思路 2.1 序列化 首先我们介绍二叉树先序序列化的方式,假设序列化的结果字符串为str,初始时str等于空字符串。先序遍历二叉树,如果遇到空节点,就在str的末尾加上“#!”,“#”表示...
  • c#中的序列化和反序列化

    千次阅读 2019-08-13 21:25:48
    第一步:什么是序列化和反序列化 序列化定义:将对象转化为容易传输的格式的过程。 反序列化定义:重新解析构造被序列化对象 第二步:为什么要序列化和反序列化 当两个进程在进行远程通信时,彼此可以发送各种...
  • 序列化和反序列化

    千次阅读 2019-06-04 16:44:52
    序列化和反序列化什么是序列化序列化高阶认识jdk序列化serialVersionUID 的作用Transient 关键字绕开 transient 机制的办法序列化小结分布式架构下常见序列化技术了解序列化的发展简单了解各种序列化技术json序列化...
  • kafka系列之序列化和反序列化

    千次阅读 2019-08-16 20:03:28
    文章目录简介基本原理分析自定义序列化组件测试 ...long,String等,这归功于kafka的序列化和反序列化机制。 基本原理分析 在之前的一篇文章springboot集成kafka示例中,我使用的是kafka原生的Str...
  • Java 序列化的几种方式 和反序列化

    千次阅读 2019-04-16 17:19:04
    对象反序列化 序列化的用途:把对象的字节序列保存在磁盘上,通常存放在一个文件中;在网络上传送对象的字节序列。 存储在物理磁盘上的:Web服务器中的Session对象。当有 10万用户并发访问,就有可能出现10万个...
  • javascript实现json的序列化和反序列化功能

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 679,332
精华内容 271,732
关键字:

对象序列化和反序列化