需要在Java中进行序列化

问题描述 投票:51回答:8

任何人都可以告诉我在Java中需要什么样的序列化以及解释需求的示例场景。我不需要这个定义。

java
8个回答
122
投票

当需要通过网络发送数据或存储在文件中时,通常会使用序列化。数据我指的是对象而不是文本。

现在的问题是您的网络基础设施和您的硬盘是理解位和字节但不了解JAVA对象的硬件组件。

序列化是将Java对象的值/状态转换为字节以通过网络发送或保存它。

这类似于您的语音通过PSTN电话线传输的方式。


149
投票

关于序列化的短篇小说

经过多年的努力,地球科学家开发出了一种可以帮助他们日常工作的机器人。但是这个机器人的功能比火星星球科学家开发的机器人要少。

在两个行星的科学家会面后,决定火星将他们的机器人送到地球。但是发生了一个问题。向地球发送100台机器人的费用为1亿美元。旅行大约需要60天。

最后,Mar的科学家决定与地球科学家分享他们的秘密。这个秘密是关于类/机器人的结构。地球科学家在地球上开发了相同的结构。 Mar的科学家将每个机器人的数据序列化并将其发送到地球。地球科学家对数据进行反序列化并相应地将其输入每个机器人。

这个过程节省了他们传递大量数据的时间。

一些机器人被用于火星上的一些防御工作。因此,在将数据发送到地球之前,他们的科学家将这些机器人的一些重要特性标记为瞬态。请注意,在对象进行反序列化时,transient属性设置为null(在引用的情况下)或默认值(在基本类型的情况下)。

地球科学家注意到的另一点是,火星的科学家要求他们创建一些静态变量来保存环境细节。一些机器人使用这些细节。但是火星的科学家并没有分享这些细节。因为地球的环境与火星的环境不同。

即使了解机器人类结构并具有序列化数据,地球科学家也无法对可以使机器人工作的数据进行反序列化。

Exception in thread "main" java.io.InvalidClassException:
SerializeMe; local class incompatible: stream classdesc
:

火星的科学家们正在等待全部付款。付款完成后,Mars的科学家们与地球科学家分享了serialversionUID。地球科学家把它设置为机器人类,一切都开始工作了。

更新

虽然在序列化的帮助下,他们能够使用信号而不是实际的太空船发送数据,他们意识到发送大量数据仍然是一个挑战。序列化使流程更便宜,更快,但仍然很慢。因此,不同的科学家提出了不同的想法来减少数据量。一些科学家建议压缩数据,有些建议使用不同的机制来表示它,以便可以反序列化。一些想法是XMLJSONmsgpackनिम्न (Nimn)


36
投票

Java序列化(特别是SerializableExernalizable接口)允许您自动或手动从/向磁盘或从/向网络读/写任意复杂的Java对象。虽然XML和JSON是文本格式,但Java序列化是二进制格式。 (序列化也是简单读/写数据的一般概念,但由于问题是关于Java,我假设你指的是内置序列化系统,即Serializable / Exernalizable)

“实现Serializable”优于XML / JSON的优点 首先,你可以免费获得序列化。您不需要对对象进行很多更改,以使序列化机制能够使用它。另一个优点是,因为它是二进制格式,它比文本格式更紧凑,因此可能使用更少的空间(这有利于节省网络带宽或节省磁盘上的存储空间)。

缺点“通过XML / JSON实现Serializable” 内置Java序列化的缺点是,如果对对象进行更改,使不同的序列化格式兼容可能真的是一个主要的噩梦。此外,您可以手动编辑XML和JSON,但不能编辑序列化Java对象(不将其读入Java)。出于同样的原因,通常比二进制格式更容易调试XML和JSON,因为XML和JSON是人类可读的。 Java内置序列化机制的另一个缺点是您无法(轻松)序列化/反序列化来自其他编程语言的数据。

用于读/写数据的替代技术 除了Java的内置序列化之外,还有其他一些序列化技术可以为您提供两全其美的优势:紧凑的二进制格式,语言互操作,易于版本兼容,以及通常的调试工具,可以轻松地以可读格式转储二进制数据。例如,Google的开源protocol buffersMessagePack是序列化库/格式的示例,可让您读/写紧凑的二进制数据并轻松维护版本兼容性。这些库相对于内置Java序列化的最大缺点是它们涉及用于序列化的普通旧数据对象(而不是具有与之关联的行为的更全功能的Java对象);然而,这个缺点实际上是一个优点,因为将存储信息的数据模型与包装或从中导出的对象分开实际上是一种很好的编程实践,并且更容易支持多种格式。

用法 由于您询问了需求,而不仅仅是定义,因此有许多用例:

  1. 只需保存您的数据以供日后使用。例如,假设您正在编写视频游戏。你的程序不会永远运行;即使它永远不会崩溃(希望是这种情况),您的用户可能会在某个时刻退出程序,或者操作系统可能会终止程序以节省资源(例如,在Android上,用户未与之交互的后台进程经常并故意被操作系统杀死以回收RAM等系统资源。为了确保用户从一开始就没有启动,而是可以从最近的保存点或从最近的保存点恢复,您将需要将游戏状态写入持久存储(即硬盘驱动器,用户的Google云端硬盘帐户等)。为此,您需要将表示游戏状态的内存中的数据结构转换为可写入磁盘的原始字节(或者保存数据的任何系统)。
  2. 从远程服务器检索信息。让我们继续游戏示例...假设您正在创建一个在线多人游戏,或者您想要在游戏中提供新级别或项目而无需用户更新他们的应用程序。为此,您需要从服务器计算机(用作各种设备上安装的应用程序的所有副本的联系点)传达有关在线播放器的信息或有关新级别/项目的信息。到应用程序的各个副本。服务器和应用程序都需要这些数据结构的某种内存表示(例如,其他玩家的位置,新级别的结构,新项目的描述/图像等),但是要传输信息从服务器到设备上的应用程序,通信系统由原始字节组成,因此有必要将数据转换为原始字节并将原始字节转换回有意义的内存数据结构。

几乎任何两个不同进程/应用程序之间或应用程序与某些存储系统之间的通信都是需要某种序列化机制的情况。


13
投票

如果要将对象的状态保存到文件中或通过网络发送,则需要将其转换为一系列字节。这称为序列化。

Java有一个内置机制,其他选项包括XML或JSON。

需要的示例:缓存对象,进行远程方法调用,将对象图保存到磁盘。


3
投票
  • 如果要在磁盘上存储对象(-structure),则需要序列化。
  • Web服务需要在将对象传输到xml之前将其序列化。

2
投票

您还可以使用序列化实现对象克隆


2
投票

序列化通常称为将Object转换为一系列位。它是java中必不可少的一个,因为java主要用于基于Web的应用程序,我的意思是使数据在网络上可用


0
投票
public class Serializer {

    public static void write(Object o, File f) throws IOException {
        f.delete();
        f.createNewFile();
        FileOutputStream fileOut = new FileOutputStream(f);
        ObjectOutputStream out = new ObjectOutputStream(fileOut);
        out.writeObject(o);
        out.close();
        fileOut.close();
    }

    public static Object read(File f) throws Exception{
        FileInputStream fileIn = new FileInputStream(f);
        ObjectInputStream in = new ObjectInputStream(fileIn);
        Object e = in.readObject();
        in.close();
        fileIn.close();
        return e;
    }

    public static byte[] toBytes(Object o) {
        byte[] bytes = null;
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutput out = null;
        try {
            out = new ObjectOutputStream(bos);
            out.writeObject(o);
            out.flush();
            bytes = bos.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                bos.close();
            } catch (IOException ex) {
                // ignore close exception
            }
        }

        return bytes;
    }

    public static Object fromBytes(byte[] bytes) {
        Object o = null;
        ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
        ObjectInput in = null;
        try {
            in = new ObjectInputStream(bis);
            o = in.readObject();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (IOException ex) {
                // ignore close exception
            }
        }

        return o;
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.