将一个对象的状态写入文件的过程被称为序列化,但严格来说,它是将一个对象从java支持的形式转换为文件支持的形式或网络支持的形式的过程通过使用fileOutputStreamobjectOutputStream类,我们可以实现序列化。

但是只能序列化可序列化的对象。当且仅当相应的类实现了可序列化的接口时,一个对象才被称为可序列化。可序列化接口存在于java.io包中,并且它不包含任何方法,因此它是一个标记性的接口。如果试图对一个不可序列化的对象进行序列化,那么将得到运行时异常,即notSerializableException异常。

例子:

import java.io.*;
import java.util.*;

// Main Class
// Class implementing serializable interface
class serializableDemo implements Serializable {

    // Member variables of this class
    String name;
    int age;
    int jobId;

    // Default constructor
    public serializableDemo(String name, int age, int jobId)
    {
        // This keyword is used to refer
        // current object instance
        this.name = name;
        this.age = age;
        this.jobId = jobId;
    }

    // Method 2
    // Main driver method
    public static void main(String[] args) throws Exception
    {

        // Creating an object of class in main() method
        serializableDemo t1 = new serializableDemo("Yiibai", 24, 2345);

        // Serialization

        // Saving of object in a file
        FileOutputStream fos
            = new FileOutputStream("abc123.ser");
        ObjectOutputStream oos
            = new ObjectOutputStream(fos);

        // Method for serialization of object
        oos.writeObject(t1);

        System.out.println("Object has been serialized");
        // Deserialization

        // Reading the object from a file
        FileInputStream fis
            = new FileInputStream("abc123.ser");
        ObjectInputStream ois = new ObjectInputStream(fis);

        // Method for deserialization of object
        serializableDemo t2
            = (serializableDemo)ois.readObject();

        // Display message only
        System.out.println("Object has been deserialized ");

        // Print and display the name and age
        // to illustrate Serializable
        System.out.println("Name:" + t2.name + "n" + "Age:" + t2.age + "n" + t2.jobId);
    }
}

运行结果:

Object has been serialized
Object has been deserialized  
Name:Yiibai
Age:24  
2345

可外部化

在序列化中,一切都由JVM负责,程序员没有任何控制权。在序列化中,总是有可能将整个对象解决到文件中,而不可能保存对象的一部分,这可能造成性能问题。为了克服这个问题,我们应该去选择外部化。

与序列化相比,可外部化的主要优点是,一切都由程序员来处理,JVM没有任何控制。根据我们的要求,可以保存整个对象或对象的一部分,从而提高系统的性能。为了给任何java对象提供可通用的能力,相应的类必须实现一个可通用的接口。

这个接口定义了以下两种方法:

方法一

public void  writeExternal( ObjectOutput obj ) throws IOException

这个方法将在序列化时自动执行,在这个方法中,必须写代码来保存所需的变量到文件中。

方法二

public void  readExternal(ObjectInput  in )throws IOException , ClassNotFoundException

这个方法将在反序列化的时候自动执行。在这个方法中,必须编写代码从文件中读取所需的变量并将其分配给当前对象。但严格来说,在反序列化的时候,JVM会通过执行一个公共的无参数构造器来创建一个单独的新对象,然后在这个对象上,JVM会调用readExternal方法。

因此,每个Externalizable实现的类都必须包含一个公共的无参数构造函数,否则会得到Runtime Exception,即InvalidClassException。

例子:

// Java Program to illustrate Externalizable

// Importing input output classes
import java.io.*;
// Importing utility classes
import java.util.*;

// Main Class
// Class implementing externalizable class
public class ExternalizableDemo implements Externalizable {

    // Member variables of this class
    String name;
    int age;
    int jobId;

    // Constructors of this class

    // Constructor 1
    // No-argument constructor
    public ExternalizableDemo()
    {

        // Display message
        System.out.println(
            "Public no-argument constructor");
    }

    // Constructor 2
    // Default constructor
    public ExternalizableDemo(String name, int age,
                            int jobId)
    {

        // This keyword refers to current object itself
        this.name = name;
        this.age = age;
        this.jobId = jobId;
    }

    // Implementing write external method
    public void writeExternal(ObjectOutput out)
        throws IOException
    {
        // Writing name and age to file
        out.writeObject(name);
        out.writeInt(age);
    }

    // Implementing readExternal method
    public void readExternal(ObjectInput in)
        throws IOException, ClassNotFoundException
    {
        // Reading name from file
        name = (String)in.readObject();

        // Reading age from file
        age = in.readInt();
    }

    // Main method
    public static void main(String[] args) throws Exception
    {

        // Creating an object of type ExternalizableDemo
        ExternalizableDemo t1 = new ExternalizableDemo("Yiibai", 24, 2345);

        // Serialization of object
        FileOutputStream fos = new FileOutputStream("abc123.ser");

        ObjectOutputStream oos = new ObjectOutputStream(fos);

        oos.writeObject(t1);

        // Deserialization
        FileInputStream fis = new FileInputStream("abc123.ser");

        ObjectInputStream ois = new ObjectInputStream(fis);

        ExternalizableDemo t2 = (ExternalizableDemo)ois.readObject();

        // Display message
        System.out.println("Name :" + " " + t2.name + " " + "Age :" + " " + t2.age);
    }
}

运行结果:

Public no-argument constructor
Name : Yiibai Age : 24

现在,我们已经完成了对它们的讨论,为了更好地理解,下面在一个表格中总结所有的区别。

可序列化 可外部化
一个可序列化的接口用于实现序列化。 一个可外部化的接口用于实现外部化
Serializable是一个标记性接口,即它不包含任何方法。 externalizable接口不是一个标记接口,因此它定义了两个方法writeExternal()和readExternal()。
可序列化接口将序列化的责任交给了JVM,程序员对序列化没有控制权,而且它是一种默认的算法。 可外部化接口将所有的序列化责任提供给程序员,因此JVM对序列化没有控制权。
使用可序列化接口的序列化性能很差。 使用可外部化接口的序列化具有更好的性能。
默认的序列化不需要任何无条件的构造函数。 在使用可外部化接口时,需要一个公共的无条件构造函数。
很难分析和修改类的结构,因为结构的任何变化都可能破坏序列化。 分析和修改类的结构相对容易,因为可以完全控制序列化逻辑。
使用一个可序列化的接口,我们将整个对象保存到一个文件中,而不可能保存对象的一部分。 根据我们的要求,我们可以保存整个对象或对象的一部分。
瞬时关键字在这里起着重要的作用。 瞬时关键字不会发挥任何作用。

Java序列化中可序列化和可外部化的区别

欢迎任何形式的转载,但请务必注明出处,尊重他人劳动成果。
转载请注明:文章转载自 有区别网 [http://www.vsdiffer.com]
本文标题:Java序列化中可序列化和可外部化的区别
本文链接:https://www.vsdiffer.com/vs/difference-between-serializable-and-externalizable-in-java-serialization.html
免责声明:以上内容仅代表 个人看法、理解、学习笔记、总结和研究收藏。不保证其正确性,因使用而带来的风险与本站无关!如本网站内容冒犯了您的权益,请联系站长,邮箱: ,我们核实并会尽快处理。