二期的毕业项目是"在线考试系统",前台要求用JSP实现,老师的要求是,学生登录后,随机生成20道试题,当遇到电脑死机或断电等异常退出考试系统时,学生在考试时间未结束之内登录考试系统,可恢复到原来考生的20道试题,以及学生填的答案,都要能够保存下来      老师说最好的方法是使用序列化,请教一下JAVA序列化是什么样的,我目前只学过C#的序列化.

解决方案 »

  1.   

    序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化。可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间。序列化是为了解决在对对象流进行读写操作时所引发的问题。序列化的实现:将需要被序列化的类实现Serializable接口,该接口没有需要实现的方法,implements Serializable只是为了标注该对象是可被序列化的,然后使用一个输出流(如:FileOutputStream)来构造一个ObjectOutputStream(对象流)对象,接着,使用ObjectOutputStream对象的writeObject(Object obj)方法就可以将参数为obj的对象写出(即保存其状态),要恢复的话则用输入流。 序列化:序列化是将对象转换为容易传输的格式的过程。例如,可以序列化一个对象,然后使用 HTTP 通过 Internet 在客户端和服务器之间传输该对象。在另一端,反序列化将从该流重新构造对象。 是对象永久化的一种机制。 
    确切的说应该是对象的序列化,一般程序在运行时,产生对象,这些对象随着程序的停止运行而消失,但如果我们想把某些对象(因为是对象,所以有各自不同的特性)保存下来,在程序终止运行后,这些对象仍然存在,可以在程序再次运行时读取这些对象的值,或者在其他程序中利用这些保存下来的对象。这种情况下就要用到对象的序列化。 对象序列化的最主要的用处就是在传递,和保存对象(object)的时候,保证对象的完整性和可传递性。譬如通过网络传输,或者把一个对象保存成一个文件的时候,要实现序列化接口
      

  2.   

    参考文章:
    Java对象的序列化和反序列化实践 http://it.21cn.com/software/jdjc/2007/09/20/3490397.shtml
      

  3.   

    序列化概述:       简单来说序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化,流的概念这里不用多说(就是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;
    }
    个人以为,此答案更合适,更详尽