`
hwy1782
  • 浏览: 153371 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Java对象序列化(整理篇) 选择自 hdAptechIvan 的 Blog

阅读更多

在网上看了很多有关序列化的文章,我自己也写了两篇,现在感觉这些文章都没有很好的把序列化说清楚(包括我自己在内),所以在此我将总结前人以及自己的经验,用更浅显易懂的语言来描述该机制,当然,仍然会有不好的地方,希望你看后可以指出,作为一名程序员应该具有不断探索的精神和强烈的求知欲望!

序列化概述:

      简单来说序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化,流的概念这里不用多说(就是I/O),我们可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间(注:要想将对象传输于网络必须进行流化)!在对对象流进行读写操作时会引发一些问题,而序列化机制正是用来解决这些问题的!

问题的引出:

      如上所述,读写对象会有什么问题呢?比如:我要将对象写入一个磁盘文件而后再将其读出来会有什么问题吗?别急,其中一个最大的问题就是对象引用!举个例子来说:假如我有两个类,分别是A和B,B类中含有一个指向A类对象的引用,现在我们对两个类进行实例化{ A a = new A(); B b = new B(); },这时在内存中实际上分配了两个空间,一个存储对象a,一个存储对象b,接下来我们想将它们写入到磁盘的一个文件中去,就在写入文件时出现了问题!因为对象b包含对对象a的引用,所以系统会自动的将a的数据复制一份到b中,这样的话当我们从文件中恢复对象时(也就是重新加载到内存中)时,内存分配了三个空间,而对象a同时在内存中存在两份,想一想后果吧,如果我想修改对象a的数据的话,那不是还要搜索它的每一份拷贝来达到对象数据的一致性,这不是我们所希望的!

以下序列化机制的解决方案:

1.保存到磁盘的所有对象都获得一个序列号(1, 2, 3等等)

2.当要保存一个对象时,先检查该对象是否被保存了。

3.如果以前保存过,只需写入"与已经保存的具有序列号x的对象相同"的标记,否则,保存该对象

通过以上的步骤序列化机制解决了对象引用的问题!

序列化的实现:

      将需要被序列化的类实现Serializable接口,该接口没有需要实现的方法,implements Serializable只是为了标注该对象是可被序列化的,然后使用一个输出流(如:FileOutputStream)来构造一个ObjectOutputStream(对象流)对象,接着,使用ObjectOutputStream对象的writeObject(Object obj)方法就可以将参数为obj的对象写出(即保存其状态),要恢复的话则用输入流。

例子:

import java.io.*;
public class Test 
{
    public static void main(String[] args) 
    {
        Employee harry = new Employee("Harry Hacker", 50000);
        Manager manager1 = new Manager("Tony Tester", 80000);
        manager1.setSecretary(harry);
        
        Employee[] staff = new Employee[2];
        
        staff[0] = harry;
        staff[1] = manager1;
        try
        {
            ObjectOutputStream out = new ObjectOutputStream(
                new FileOutputStream("employee.dat"));
            out.writeObject(staff);
            out.close();
            
            ObjectInputStream in = new ObjectInputStream(
                new FileInputStream("employee.dat"));
            Employee[] newStaff = (Employee[])in.readObject();
            in.close();
   
            /**
             *通过harry对象来加薪
             *将在secretary上反映出来
             */
            newStaff[0].raiseSalary(10);
            
            for (int i = 0; i < newStaff.length; i++)
                System.out.println(newStaff[i]);
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }
    
}
class Employee implements Serializable
{
    public Employee(String n, double s)
    {
        name = n;
        salary = s;
    }
    
    /**
     *加薪水
     */
    public void raiseSalary(double byPercent)
    {
        double raise = salary * byPercent / 100;
        salary += raise;
    }
    
    public String toString()
    {
        return getClass().getName()
            + "[name = "+ name
            + ",salary = "+ salary
            + "]";
    }
    
    private String name;
    private double salary;
}
class Manager extends Employee
{
    public Manager(String n, double s)
    {
        super(n, s);
        secretary = null;
    }
    
    /**
     *设置秘书
     */
    public void setSecretary(Employee s)
    {
        secretary = s;
    }
    
    public String toString()
    {
        return super.toString()
            + "[secretary = "+ secretary
            + "]";
    }
    
    //secretary代表秘书
    private Employee secretary; 
}
 

修改默认的序列化机制:   

      在序列化的过程中,有些数据字段我们不想将其序列化,对于此类字段我们只需要在定义时给它加上transient关键字即可,对于transient字段序列化机制会跳过不会将其写入文件,当然也不可被恢复。但有时我们想将某一字段序列化,但它在SDK中的定义却是不可序列化的类型,这样的话我们也必须把他标注为transient,可是不能写入又怎么恢复呢?好在序列化机制为包含这种特殊问题的类提供了如下的方法定义:

private void readObject(ObjectInputStream in) throws
         IOException, ClassNotFoundException;
private void writeObject(ObjectOutputStream out) throws
         IOException;
 

(注:这些方法定义时必须是私有的,因为不需要你显示调用,序列化机制会自动调用的)

使用以上方法我们可以手动对那些你又想序列化又不可以被序列化的数据字段进行写出和读入操作。

      下面是一个典型的例子,java.awt.geom包中的Point2D.Double类就是不可序列化的,因为该类没有实现Serializable接口,在我的例子中将把它当作LabeledPoint类中的一个数据字段,并演示如何将其序列化!

import java.io.*;
import java.awt.geom.*;
public class TransientTest 
{
    public static void main(String[] args) 
    {
        LabeledPoint label = new LabeledPoint("Book", 5.00, 5.00);
        try
        {
            System.out.println(label);//写入前
            ObjectOutputStream out = new ObjectOutputStream(new
                FileOutputStream("Label.txt"));
            out.writeObject(label);
            out.close();
            
            System.out.println(label);//写入后
            
            ObjectInputStream in = new ObjectInputStream(new
                FileInputStream("Label.txt"));
            LabeledPoint label1 = (LabeledPoint)in.readObject();
            in.close();
            System.out.println(label1);//读出并加1.0后
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }
    
}
class LabeledPoint implements Serializable
{
    public LabeledPoint(String str, double x, double y)
    {
        label = str;
        point = new Point2D.Double(x, y);
    }
    
    private void writeObject(ObjectOutputStream out) throws IOException
    {
        /**
         *必须通过调用defaultWriteObject()方法来写入
         *对象的描述以及那些可以被序列化的字段
         */
        out.defaultWriteObject();
        out.writeDouble(point.getX());
        out.writeDouble(point.getY());
    }
    
    private void readObject(ObjectInputStream in)
        throws IOException, ClassNotFoundException
    {
        /**
         *必须调用defaultReadObject()方法
         */
        in.defaultReadObject();
        double x = in.readDouble() + 1.0;
        double y = in.readDouble() + 1.0;
        point = new Point2D.Double(x, y);
    }
    
    public String toString()
    {
        return getClass().getName()
            + "[label = "+ label
            + ", point.getX() = "+ point.getX()
            + ", point.getY() = "+ point.getY()
            + "]";
    }
    
    private  String label;
    transient private Point2D.Double point;
}
 

 

分享到:
评论

相关推荐

    Java对象序列化和反序列化工具Xson.zip

    Xson是一个Java对象序列化和反序列化程序。支持Java对象到字节数组的序列化,和从字节数组到Java对象的反序列化。 Maven:  &lt;groupId&gt;com.github.xsonorg&lt;/groupId&gt;  &lt;artifactId&gt;xson-core  &lt;version&gt;1.0.1 ...

    Java对象序列化标准最新版

    由于Java对象可能会随着时间发生变化,因此需要一套机制来管理序列化对象的版本。这样可以确保即使对象的结构发生了变化,仍然能够正确地进行序列化和反序列化。 **5.2 目标** 版本管理的目标是在对象结构发生变更...

    关于 Java 对象序列化您不知道的 5 件事

    Java对象序列化不仅用于持久化对象状态,还能在网络传输中扮演关键角色,例如在RMI(远程方法调用)中。此外,它还可以作为缓存和备份数据的一种手段。通过实现`java.io.Serializable`接口,一个类的实例就能被序列...

    java 对象序列化

    Java对象序列化是一种将Java对象转换为字节流的过程,以便可以存储在磁盘上、在网络上传输或在任何其他需要持久化数据的场景中使用。这个过程涉及到两个主要概念:序列化(Marshalling)和反序列化(Unmarshalling)...

    JAVA对象序列化保存为XML文件的工具类

    在某些情况下,我们可能希望将这些序列化对象以XML格式存储,以便于阅读和编辑。`java.beans`包中的`XMLEncoder`和`XMLDecoder`就是为此目的设计的。 `XMLEncoder`是一个用于将Java对象编码为XML输出流的类,它能够...

    java对象序列化.ppt

    Java对象序列化是一种将对象转换为字节流的过程,以便可以将其存储在磁盘上,或者在网络中进行传输。这是Java平台提供的一种功能,允许程序员将任何Java对象持久化,即将其状态保存到磁盘,或者在网络中进行传输。...

    Java对象序列化的秘密

    Java对象序列化是Java平台提供的一种机制,允许将对象的状态转换为字节流,以便存储在磁盘上、通过网络传输或在不同时间点恢复。这个过程涉及到将一个复杂的Java对象模型转换为简单的二进制表示,使得数据可以在不同...

    介绍Java对象序列化使用基础

    序列化的过程就是对象写入字节流和从字节流中读取对象。将对象状态转换成字节流之后,可以用java.io包中的各种字节流类将其保存到文件中,管道到另一线程中或通过网络连接将对象数据发送到另一主机。对象序列化功能...

    java对象序列化 传输 保存

    Java对象序列化是一种将Java对象转换为字节流的过程,以便可以存储这些对象或通过网络进行传输。这个过程是Java平台的核心特性,它允许开发者将复杂的对象结构持久化或者在网络间进行安全通信。序列化不仅可以用于...

    java反序列化工具

    攻击者可以构造恶意的序列化对象,当它被目标应用反序列化时,可能会触发任意代码执行、权限提升或其他安全漏洞。这些漏洞通常利用了类库中的特性和设计缺陷,例如默认的信任所有反序列化数据,或者没有充分验证输入...

    java序列化对象传给php

    android(包括java)序列化一个对象传给php去做处理,或是接到php的序列化的对象在java中做处理的工具jar包以及使用方法. 使用方法: byte[] b = null; b = PHPSerializer.serialize(一个对象);//将一个对象序列化后返回...

    java序列化和反序列化的方法

    Java 序列化和反序列化是 Java 语言中的一种机制,用于将对象转换为字节流,以便在网络上传输或存储。序列化是将对象转换为字节流的过程,而反序列化是将字节流转换回对象的过程。 在 Java 中,序列化和反序列化是...

    java自动序列化

    Java自动序列化是一种在Java编程语言中用于持久化对象的技术,它允许我们将对象的状态转换为字节流,以便可以存储或在网络上传输。这在分布式应用程序、数据存储和跨网络进程通信中非常常见。本篇文章将深入探讨Java...

    C#和Java的序列化反序列化

    本篇文章将深入探讨C#和Java中的序列化与反序列化机制。 首先,我们要了解什么是序列化。序列化是指将对象的状态转化为可存储或可传输的数据格式的过程。这个过程通常将内存中的对象转换成字节流,以便保存到磁盘、...

    Java对象的序列化和反序列化实践

    前者用于写入序列化对象,后者用于读取反序列化的对象。 **反序列化(Deserialization)** 1. **概念**:反序列化是将已序列化的字节流恢复为原来的Java对象的过程。 2. **过程**:通过`ObjectInputStream`的`...

    java反序列化利用程序UI版Beta1.1.rar

    `ObjectOutputStream`用于将对象写入流,`ObjectInputStream`用于从流中读取并反序列化对象。 2. **易受攻击的库**:许多常用的Java库,如Apache Commons Collections、Apache POI、OpenJDK等,都曾因不安全的反...

    Java序列化_Java序列化结构_

    Java序列化是Java平台中的一种持久化机制,它允许对象的状态被转换成字节流,以便存储、网络传输或在不同时间点恢复。这个过程被称为序列化,而反向操作称为反序列化。序列化在许多场景下都非常有用,比如在分布式...

    Java对象序列化

    Java对象序列化是Java平台提供的一种将对象的状态转化为字节流,以便存储或者在网络中传输的技术。这个过程称为序列化,而将字节流恢复为原来的对象状态则称为反序列化。序列化对于数据持久化、网络通信以及跨进程...

Global site tag (gtag.js) - Google Analytics