首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > JAVA > J2SE开发 >

关于对象序列化小例子的2个小有关问题

2011-11-22 
关于对象序列化小例子的2个小问题。请看注释问题。Java codeimport java.io.*public class ObjectTest impl

关于对象序列化小例子的2个小问题。
请看注释问题。

Java code
import java.io.*; 

public class ObjectTest implements Serializable {
static private int a;            //问题1:static 和 transient的字段不是不能序列化的吗?(这在jdk ObjectOutputStream类中有说过)
static String s;

//public ObjectTest(){System.out.println("Constructor");}  //问题2:我把默认的构造器注释起来居然也能运行(这在jdk Serializable接口中有说过)
public ObjectTest(int a, String s){
this.a = a;
this.s = s;
}

//private void writeObject(java.io.ObjectOutputStream out)throws IOException{
//out.writeInt(a);
//out.writeObject(s);
//}
//
//private void readObject(java.io.ObjectInputStream in)throws IOException,ClassNotFoundException{
//a = in.readInt();
//s = (String)in.readObject();
//}

public String toString(){
return "a = " + a + ",  s = " + s;
}
public static void main(String[] args)throws IOException, ClassNotFoundException{
ObjectTest ot = new ObjectTest(1, "a");
System.out.println("Test one:");
System.out.println(ot);

BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream("D:\\333\\OOO.test"));
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(ot);
oos.close();

BufferedInputStream bis = new BufferedInputStream(
new FileInputStream("D:\\333\\OOO.test"));
ObjectInputStream ois = new ObjectInputStream(bis);
ObjectTest ot2 = (ObjectTest)ois.readObject();
ois.close();

System.out.println("Test two:");
System.out.println(ot2);
}
}


[解决办法]
新年快乐,帮你顶一下。
[解决办法]
我说下问题一吧
静态和transient域在对象被序列化时会被跳过
就是说这些域不会被写入
下面是一个例子
transient int a未被写入
Java code
import java.io.*;import java.util.*;public class Test implements Serializable{    public transient int a;        public Test(){ }        public static void main(String[] args)    {        Test t = new Test();        t.a = 10;        System.out.println("t.a = " + t.a);                try        {            ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("t.dat"));            out.writeObject(t);            out.close();                        ObjectInputStream in = new ObjectInputStream(new FileInputStream("t.dat"));            Test nt = (Test)in.readObject();            in.close();                        System.out.println("nt.a = " + nt.a);        }        catch(Exception e){e.printStackTrace();}    }}
[解决办法]
第一个问题。static 和 transient的字段事实上并没有序列化。
反序列化输出的是类的值。
如果该成这样
Java code
oos.close();[color=#FF0000]ObjectTest.a=2;[/color]   BufferedInputStream bis = new BufferedInputStream(              new FileInputStream("D:\\333\\OOO.test"));
[解决办法]
static的数据没有被序列化。之所以你的测试看起来好像是被序列化了,原因是static的数据在内存中使用都是只有一份,你把代码改称下面这样子

 public static void main(String[] args)throws IOException, ClassNotFoundException{
ObjectTest ot = new ObjectTest(1, "a");
System.out.println("Test one:");
System.out.println(ot);

BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream("D:\\333\\OOO.test"));
ObjectOutputStream oos = new ObjectOutputStream(bos);


oos.writeObject(ot);
oos.close();

ot.a = 99;
ot.s = "bluesmile979";

BufferedInputStream bis = new BufferedInputStream(
new FileInputStream("D:\\333\\OOO.test"));
ObjectInputStream ois = new ObjectInputStream(bis);
ObjectTest ot2 = (ObjectTest)ois.readObject();
ois.close();

System.out.println("Test two:");
System.out.println(ot2);
}

或者把read程序单独做一个类,单独执行。就能看到效果了


至于默认构造函数的问题,你写不写java好像都会自动加上一个没有参数什么都不做的构造函数。具体自己去查一下,既不太清楚了。
[解决办法]

探讨
transient的字段我试过了确实是不能序列化的,但是上面的那段代码static字段却可以,你们先运行了试试看。

[解决办法]

嗯,用五楼这种方法就可以检测出来。

另外,你能读出来是因为你之前所创建的对象仍然存在在内存中,并没有被回收掉。而static是所有同类对象共享的,所以你能打印出来。
[解决办法]
探讨
至于默认构造函数的问题,你写不写java好像都会自动加上一个没有参数什么都不做的构造函数。具体自己去查一下,既不太清楚了。

[解决办法]
如果你没写构造函数,编译器会给一个默认的无参数的构造函数。只要你写了构造函数编译器就不提供任何默认的构造函数了,所以的都要自己写。
[解决办法]
我去查了一下API,可能是大家对API的理解上出了一点差错。发出来大家一起看一下


类通过实现 java.io.Serializable 接口以启用其序列化功能。未实现此接口的类将无法使其任何状态序列化或反序列化。可序列化类的所有子类型本身都是可序列化的。序列化接口没有方法或字段,仅用于标识可序列化的语义。

要允许不可序列化类的子类型序列化,可以假定该子类型负责保存和恢复超类型的公用 (public)、受保护的 (protected) 和(如果可访问)包 (package) 字段的状态。仅在子类型扩展的类有一个可访问的无参数构造方法来初始化该类的状态时,才可以假定子类型有此职责。如果不是这种情况,则声明一个类为可序列化类是错误的。该错误将在运行时检测到。


重点在于要允许不可序列化类的子类型序列化,子类型扩展的类有一个可访问的无参数构造方法来初始化该类的状态才是必须的。也许API是这个意思。

热点排行