java序列化机制

什么是序列化和反序列化?

把对象转化为字节序列的过程称之为对象的序列化,反之,称之为反序列化。

为啥要序列化?

一旦对象被序列化后,它的编码就可以从一台正在运行的虚拟机被传递到另一台虚拟机上,或者被存储到磁盘上,供以后反序列化时用。序列化技术为远程通信提供了标准的线路级对象表示法,也为JavaBeans组件结构提供了标准的持久化数据格式。

如何实现?

1.java本身的序列化机制:

1)实现Serializable接口

2)ObjectOutputStream:表示将具体的对象转化成字节数据

3)ObjectInputStream:表示读取指定的字节数据转化成对象

设置一个需序列化的类:Person.java,实现接口Serializable接口,生成一个唯一编号serialVersionUID。


public class Person  implements Serializable{

    private static final long serialVersionUID = -5959771684631696017L;
    private String name;
    private int age;
    private int hight;

   //===============get、set 方法省略==========

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", hight=" + hight +
                '}';
    }
}

进行序列化和反序列化操作:

       序列化:new ObjectOutputStream(new FileOutputStream(new File("person"))); 生成字节码文件

       反序列化:new ObjectInputStream(new FileInputStream(new File("person")));  生成一个对象

 
public class SerializeDemo {
    public static void main(String[] args) {
        //序列化操作
        serializePerson();
        //反序列化操作
        Person person = deSerializePerson();
        System.out.println(person);
    }
   //序列化操作
    private static void serializePerson() {
        try {
            ObjectOutputStream oo=new ObjectOutputStream(new FileOutputStream(new File("person")));
            Person person=new Person();
            person.setName("fang");
            person.setAge(20);
            person.setHight(175);
            oo.writeObject(person);
            oo.flush();
            System.out.println("序列化成功:"+new File("person").length());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    //反序列化
    private static Person deSerializePerson(){
        ObjectInputStream ois=null;
        try {
            ois= new ObjectInputStream(new FileInputStream(new File("person")));
            Person person = (Person) ois.readObject();
            return person;
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }
}

运行main方法:

序列化成功:116
Person{name='fang', age=20, hight=175}

serialVersionUID作用:

字节码文件反序列化过程中,根据自身serialVersionUID找本地对应的class文件为模板,来生成对象,如果uid一致,就能反序列成功。

          如果java文件没有显示的生成serialVersionUID,java对象序列化时,java编译器会自动生成一个serialVersionUID,但java文件一旦进行修改,编译时会重新生成一个serialVersionUID,此时反序列化时,流文件中的serialVersionUID与本地class文件serialVersionUID不一致而导致出错。

 

静态变量序列化:

Person类添加一个静态属性son.

 
public class Person  implements Serializable{

  private static final long serialVersionUID = -5959771684631696017L;
    @Protobuf
    private String name;
    @Protobuf
    private int age;
    private int hight;
    //添加一个静态变量
    public static String son;

    //=================get、set方法省略====================

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", hight=" + hight +
                '}';
    }
}

测试案例中对象序列化前对静态变量赋值【fangyifei

//序列化
private static void serializePerson() {
        try {
            ObjectOutputStream oo=new ObjectOutputStream(new FileOutputStream(new File("person")));
            Person person=new Person();
            person.setName("fang");
            person.setAge(20);
            person.setHight(175);
            person.son="fangyifei";
            oo.writeObject(person);
            oo.flush();
            System.out.println("序列化成功:"+new File("person").length());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

 测试案例中:main方法重新new一对象person1,赋值fangyiming

 public static void main(String[] args) {
        serializePerson();
        Person person1 = new Person();
        person1.son="fangyiming";
        Person person = deSerializePerson();
        System.out.println(person.son);
    }

测试结果:

序列化成功:116
fangyiming

感觉应该读取反序列化后的对象person中son值,却读取person1对象中值【fangyiming】

也就是说序列化时,并未保存静态变量的状态,而是读取了本地对象中静态变量值。

transient字段的使用:

字段age被transient修饰

private transient int age;

测试结果:

序列化成功:106
Person{name='fang', age=0, hight=175}

age不是值20,而是默认值0,说明age字段未参与序列化

序列化的存储机制:

 

java本身的序列化机制的缺点:

1)序列化的结果比较大,传输效率比较低

2)不能夸语言对接

       以至于在后来的很长一段时间,基于XML格式编码的对象序列化机制成为了主流,一方面解决了多语言兼容问题,另一方面比二进制的序列化方式更容易理解。以至于基于XML的SOAP协议及对应的WebService框架在很长一段时间内成为各个主流开发语言的必备的技术。

再到后来,基于JSON的简单文本格式编码的HTTP REST接口又基本上取代了复杂的Web Service接口,成为分布式架构中远程通信的首要选择。但是JSON序列化存储占用的空间大、性能低等问题,同时移动客户端应用需要更高效的传输数据来提升用户体验。在这种情况下与语言无关并且高效的二进制编码协议就成为了大家追求的热点技术之一。首先诞生的一个开源的二进制序列化框架-MessagePack。它比google的Protocol Buffers出现得还要早

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java序列化机制Java语言中的一种重要机制,它可以将Java对象转换为字节序列,以便在网络上传输或在文件中存储。Java序列化机制由两个部分组成:序列化和反序列化。 1. 序列化 序列化是将Java对象转换为字节序列的过程,这个过程可以通过将对象写入输出流来完成。Java提供了两个主要的序列化类:ObjectOutputStream和ObjectInputStream。 ObjectOutputStream类是用来将Java对象写入输出流的,它可以将Java对象转换为字节序列,并将字节序列写入输出流。序列化的过程中,ObjectOutputStream会将对象的类信息和实例数据都写入输出流中。 2. 反序列化序列化是将字节序列转换为Java对象的过程,这个过程可以通过读取输入流来完成。Java提供了两个主要的反序列化类:ObjectInputStream和ObjectOutputStream。 ObjectInputStream类是用来从输入流中读取字节序列的,并将其转换为Java对象。反序列化的过程中,ObjectInputStream会从输入流中读取对象的类信息和实例数据,并重新创建Java对象。 3. 序列化机制的实现原理 Java序列化机制的实现原理是通过将Java对象转换为字节序列并将其写入输出流中,然后通过读取输入流将字节序列转换为Java对象。 Java序列化机制的实现过程中,所有的类都必须实现Serializable接口。这个接口没有任何方法,只是标识了该类可以被序列化Java序列化机制还需要注意一些问题,比如序列化的版本号、序列化的安全性、序列化的性能等。为了提高序列化的性能,可以使用一些优化技巧,比如使用transient关键字防止某些字段被序列化、使用Externalizable接口替代Serializable接口等。 总之,Java序列化机制Java语言中非常重要的一种机制,它可以实现Java对象的跨平台传输和持久化存储。在开发中,需要注意序列化的版本号、安全性和性能等问题,以确保程序的正确性和性能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值