`

java Serialization

 
阅读更多
1. 什么是Serialization?

串行化(Serialization)是计算机科学中的一个概念,它是指将对象存储到介质(如文件、内在缓冲区等)中或是以二进制方式通过网络传输。之后可以通过反串行化从这些连续的位数据重新构建一个与原始对象状态相同的对象,因此在特定情况下也可以说是得到一个副本,但并不是所有情况都这样。

Java有Serialization API为开发者提供了一种标准的机制来串行化类。

2. 为什么要Serilzation?

特别地,串行化主要有三种用途:
1)作为一种持久化机制
    如果使用的是FileOutputStream流的方式,则数据将被自动地写入文件中,
2)作为一种复制机制
    如果使用的是ByteArrayOutputStream流的方式,数据将写入内存中的字节数组中。该字节数组可以用来创建初始对象的副本,
3)作为一种通信机制
    如果是使用套接字(Socket)流的方式,则数据自动地通过网络连接传输一另一个端点,并由这个端点上的程序来决定做什么。

3. Serialization的基本用法默认机制

将要串行化的类必须实现java.io.Serializable接口,或者是继承实现了该接口的类。然后通过java.io.ObjectOutputStream类来实现持久化,如果用保存到文件上还需要用到java.io.FileOutputStream类。因为ObjectOutputStream被认为是java.io包中的高级类所以可用它来包装低级的类FileOutputStream。在持久化过程中调用的一个方法是ObjectOutputStream对象的writeObject(obj)方法。

当要从文件中恢复对象时,则是使用java.io.OjbectInputStream与FileInputStream类,调用一方法是ObjectInputStream对象的readObject()方法。

示例1:

import java.io.*;

public class Cat implements Serializable {
    private String name;
    public Cat () {
        this.name = "new cat";
    }

    public String getName() {
        return this.name;
    }

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


import java.io.*;

public class CatDemo {
    public static void main(String[] args) {
        Cat cat = new Cat();
        try { //串行化
            FileOutputStream fos = new FileOutputStream("catDemo.out");
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            System.out.println(" 1> " + cat.getName());
            cat.setName("My Cat");   
        oos.writeObject(cat);
            oos.close();         
        } catch (IOException ex) {
            ex.printStackTrace();
        }

        try { //反串行化
            FileInputStream fis = new FileInputStream("catDemo.out");
            ObjectInputStream ois = new ObjectInputStream(fis);

            cat = (Cat) ois.readObject();
           
            System.out.println(" 2> " + cat.getName());
            ois.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }catch(ClassNotFoundException ex) {    
        ex.printStackTrace();
    }

    }
}



4. Serialization常见问题

正如前面提到的,所有可串行化的类必须直接或是通过继承方式间接地实现java.io.Serializable接口,由于Object类关没有实现这个接口,所以并不是所有类的对象都是可串行化的。像AWT与Swing的GUI组件、字符串、数组等都是可串行化的,而像一些系统级的类(Thread,OutputStream 等)和Socket类是不可串行化的。

问题一:如果在一个可串行化的类中Has-As不可串行化的类该怎么处理?
在这种情况下在运行时会抛出NotSerializableException。

为了解决类似问题,Java中提供了transient关键字来跳过对不可串行化类的对象的处理。但这依然可能会引起一些问题,在反串行化时,被标识为transient变量不会恢复到其原始状态,而是提供默认值,如示例2中的pig引用将赋值为null,age变量赋值为0;

附:基本类型和引用类型的默认值
对象引用:null
byte, short, int, long :0
float, double:0.0
boolean:false
char:'\u0000'(这是Unicode字符集的空格)


示例2:
import java.io.*;
public class NewPig2 implements Serializable {
    private String newName;
    private transient Pig pig = new Pig();
    private transient int age = 2;  
    public NewPig2() {
        newName = "new Pig 2";
        //pig = new Pig();
    }
    public Pig getPig() {
        return this.pig;
    }
    public void setName(String name) {
        this.newName = name;
    }
    public String getName() {
        return this.newName;
    }
    public int getAge() {
        return this.age;
    }
}

问题二:如果父类不可串行化,子类实现了Serializable会怎样?
如果有一个Animal类是不可串行化的,而有一个Dog类继承自Animal类并且实现了Serializabl接口,则没有串行化时没有任何问题,但是在反串行化时将会重新调用Animal的构造函数,如示例3所示。

示例3的运行结果如下:

1> No Color - new Dog
2> Green - My Dog
4> No Color - My Dog
因为Animal不可串行化,所以必须运行构造函数,但不会在实现Serializable的反串行化类上运行构造函数。

示例3:

public class Animal {
    private String color;
    public Animal () {
        this.color = "No Color";
    }

    public void setColor(String color) {
        this.color = color;
    }
    public String getColor () {
        return this.color;
    }
}


import java.io.*;
public class Dog extends Animal implements Serializable {
    private String name;
    public Dog () {
        this.name = "new Dog";
    }
    public String getName() {
        return this.name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

import java.io.*;
public class DogTest {
    public static void main(String[] args) {
        Dog dog = new Dog();  
        System.out.println(" 1> " + dog.getColor() + " - " + dog.getName());
        dog.setColor("Green");
        dog.setName("My Dog");
        System.out.println(" 2> " + dog.getColor() + " - " + dog.getName());
        try {//串行化
            FileOutputStream fos = new FileOutputStream("myDog.out");
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            oos.writeObject(dog);
            oos.close();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        try {//反串行化
            FileInputStream fis = new FileInputStream("myDog.out");
            ObjectInputStream ois = new ObjectInputStream(fis);
            dog = (Dog) ois.readObject();       
            System.out.println(" 4> " + dog.getColor() + " - " + dog.getName());
            ois.close();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}

5.
自定义默认方法:使用writeOject和readObject

假如在一个可以串行化的类中有一个不可串行化的对象,但又想保存该对象的状态信息该如何是好?在这样情况下可以在这个可串行化的类中实现writeObject()和readObject()。

示例4:
import java.io.*;
import java.util.Scanner;

public class NewPig3 implements Serializable {
    private String newName;
    private transient Pig pig = new Pig();
    private transient int age = 2;
   
    public NewPig3() {
        newName = "new Pig 3";
        //pig = new Pig();
    }

    private void writeObject(ObjectOutputStream oos) throws IOException {
        oos.defaultWriteObject();
        oos.writeChars(pig.getName());
    //oos.writeInt(this.age);
    }

    private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
        ois.defaultReadObject();
        pig = new Pig();
        Scanner in = new Scanner(ois);
        if (in.hasNextLine()) {   
            pig.setName(in.nextLine());
        }
    }

    public Pig getPig() {
        return this.pig;
    }

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

    public String getName() {
        return this.newName;
    }

    public int getAge() {
        return this.age;
    }
} 
 
分享到:
评论

相关推荐

    Faster Java Serialization-开源

    "Faster Java Serialization"项目正是为了解决这个问题而诞生的,它通过采用开源的方式,提供了比默认Java序列化更快的实现。这个项目的核心在于运行时生成定制的序列化代码,以优化序列化和反序列化过程。这种做法...

    基于Java的brap(Java远程调用框架 BRAP).zip

    - **序列化与反序列化**:BRAP使用高效的序列化技术,如Google的Protocol Buffers或Java自带的Java serialization,将对象转换为字节流在网络中传输,到达目的地后再反序列化恢复为对象。 - **通信协议**:BRAP...

    Java windows 课程设计

    Java Serialization - **序列化概述**:Java 中的对象可以通过实现 `Serializable` 接口来支持序列化。序列化是指将对象的状态转换为字节流的过程,以便能够将其保存到磁盘上或通过网络传输。 - **序列化的使用**...

    java Streams and Serialization 详解

    ### Java Streams 和 Serialization 详解 在Java编程语言中,数据的读取与写入操作是通过流(Streams)实现的。此外,为了保存对象的状态,Java提供了序列化(Serialization)机制。本文将深入探讨Java中的流操作...

    Effective Java 3rd edition(Effective Java第三版英文原版)附第二版

    Item 85: Prefer alternatives to Java serialization Item 86: Implement Serializable with great caution Item 87: Consider using a custom serialized form Item 88: Write readObject methods defensively ...

    marshalsec.pdf

    这意味着,即使不是所有序列化机制都像Java Serialization那样功能强大,它们仍然可以成为攻击者的利用目标。 7. 安全建议 虽然文档并未明确提供具体的解决方案,但从中可以推断出,开发者和安全研究人员应采取以下...

    JavaSerializationjavaTutorial.pdf 英文原版

    Java Serialization, java Tutorial

    nginx+tomcat+memcached 所需jarmemcached相关jar包和序列化对应的jar包

    因此,你需要添加如`java serialization`相关的jar包,例如`serp.jar`(用于Java反序列化)或者`kryo`、`FST`等第三方序列化库,以支持Java对象的序列化和反序列化。 在实际部署中,你可能需要按照以下步骤操作: ...

    Experiences Implementing Efficient Java Thread Serialization

    ### 实现高效Java线程序列化、移动性和持久性的经验 #### 概述 随着分布式计算的发展,移动性与持久性成为了重要的组成部分。这些特性在负载均衡、容错以及应用程序的动态重构等领域有着广泛的应用场景。Java作为...

    34_dubbo都支持哪些通信协议以及序列化协议?.zip

    1. **Java Serialization**:Java平台默认的序列化方式,简单易用,但性能较差,且序列化的对象必须实现Serializable接口。 2. **Hessian2**:一种快速的二进制序列化协议,它将Java对象转换为高效的字节流,适合于...

    JINI核心技术pdf

    - **Java序列化(Java Serialization)**:JINI使用Java序列化机制来传递服务的接口和实现。 - ** Lease管理**:服务和客户端之间的租约机制,用于控制服务使用时间,确保服务的可靠性和容错性。 ### 2. JINI服务...

    Java序列化(Serialization) 机制

    Java序列化机制是Java平台提供的一种标准方法,用于将对象的状态转换为字节流,以便存储在磁盘上,或者在网络中进行传输。这使得Java对象可以在不同的Java虚拟机(JVM)之间交换,这对于分布式应用程序,如远程方法...

    myRpc一个极简单的RPC框架

    是否使用了标准的序列化库,如Java的Java serialization,或是自定义的机制? - 请求和响应的网络传输部分是如何设计的?是基于HTTP还是直接TCP连接? - 调用处理中如何实现同步/异步调用,以及错误处理? 通过研究...

    kryo1.03.jar

    Fast, efficient Java serialization java序列化jar包

    java 中Spark中将对象序列化存储到hdfs

    Spark 提供了多种序列化方式,如 Java Serialization、Kryo Serialization 和 Java Serialization 等。在这篇文章中,我们使用 Java Serialization 将对象序列化。 知识点 2:HDFS 的存储 HDFS(Hadoop Distributed...

    JINI技术规范

    4. **Java序列化(Java Serialization)**:JINI技术依赖于Java的序列化机制来跨网络传输对象。服务提供者和消费者之间的通信通常涉及对象的序列化和反序列化。 5. **信任模型(Trust Model)**:由于JINI允许网络...

    详解Java在redis中进行对象的缓存

    Java提供了多种序列化机制,如Java Serialization、JSON Serialization等。在本篇文章中,我们将使用Java Serialization进行序列化。 存储对象 为了存储对象,我们需要将对象序列化成字节数组,然后将其存储在...

    dubbo视频教程地址.txt

    此外,Dubbo还提供了多种序列化协议(如Hessian、Java serialization等),用户可以根据实际需求选择合适的协议以优化网络传输性能。 #### 3. 智能路由与负载均衡 为了实现更高效的服务调度,Dubbo内置了一套智能...

Global site tag (gtag.js) - Google Analytics