A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

书上说 ObjectinputStream和ObjectoutputStream不会保存和读取对象中的transient和static类型的成员变量。但是我做的transient是可以实现不保存的功能,static修饰的怎么没有实现啊,还是会出现。百度找到一个博客里面的代码例子,我试了下还是只能一个有用。有没哪位大神解释一下两个方法的区别和我的错误在哪里?


我用的代码,张孝祥老师JAVA就业培训教材P263也例子。
/*
ObjectinputStream ObjectoutputStream ,保存和读取对象成员变量取值。需要实现Serializable(序列化)接口。
被变量修饰符 transient(短暂的,临时的) 静态修饰符 static修饰的成员变量不会保存和读取。
使用ObjectinputStream与ObjectoutputStream类保存和读取对象的机制叫序列化。
*/
import java.io.*;
public class Serialization
{
public static void main(String[] args) throws IOException,ClassNotFoundException
{
  Student stu=new Student(19,"dingding",50,"huaxue");
  FileOutputStream fos=new FileOutputStream("mytext.txt");//节点流FileOutputStream 创建流节点 mytext.txt文件。
  ObjectOutputStream os=new ObjectOutputStream(fos);//过滤流类(处理流类、包装类)ObjectOutputStream调用节点流类实例对象fos
  
  try
  {
   os.writeObject(stu);//过滤流类实例对象 os调用writeObject()方法写入stu数据。
   os.close();//关闭流。释放资源。
  }
  catch (IOException e)
  {
    System.out.println(e.getMessage());
  }
  stu=null;
  FileInputStream fi=new FileInputStream("mytext.txt");
  ObjectInputStream si=new ObjectInputStream(fi);
  try
  {
   stu=(Student)si.readObject();//利用类中的readObject()和 writeObject()方法可以读/写对象流。
   si.close();
  }
  catch (IOException e)
  {
   System.out.println(e.getMessage());
  }
   System.out.println("ID IS  "+stu.id);
    System.out.println("name is  "+stu.name);
     System.out.println("age is  "+stu.age);
      System.out.println("department is  "+stu.department);
}
}
class Student implements Serializable
{
transient int id;//transient 修饰的不能保存和读取,输出结果为0.
transient String name;
static int age;//奇怪,static修饰的可以存储读取,有待解决。
static String department;
public Student(int id,String name,int age,String department)
{
  this.id=id;
  this.name=name;
  this.age=age;
  this.department=department;
}
}


百度到的一个例子:
import java.io.*;
class Person implements Serializable
{
   private String name ;
  /* transient*/  private int age ;
   public static String address;/**/
   public Person(String name, int age)
   {
       this.name = name ;
       this.age = age ;
   }
   //覆写toString()方法
    public String toString()
    {
      return "姓名 =" + this.name +", 年龄 =" + this.age +",住址="+address;
    }

}
public class serializableDemo
{
   public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException
   {
      //1.先序列化  
      Person per = new Person("gzg",26);
      per.address = "西门";
      ser(per);
      //2.反序列化
      System.out.println(dser());  
   }
   //建立一个对象序列化的方法
   public static void ser(Person per) throws FileNotFoundException, IOException
   {
      ObjectOutputStream oos = null;
      //序列化时,保存的文件的后缀名随便取,不是关键
      oos =  new ObjectOutputStream(new FileOutputStream(new File("d://gzg4.jpg")));
      oos.writeObject(per);
      oos.close();
   }
   //建立一个反序列化的方法
   public static Person dser() throws FileNotFoundException, IOException, ClassNotFoundException
   {
      ObjectInputStream ois = null;
      ois = new ObjectInputStream(new FileInputStream(new File("d://gzg4.jpg")));
      Object obj = null;
      obj = ois.readObject();
      return (Person)obj;
   }
}

评分

参与人数 1技术分 +1 收起 理由
田磊阳 + 1

查看全部评分

4 个回复

倒序浏览
本帖最后由 贾振凯 于 2013-4-11 23:44 编辑
  1. public class SerialTest {

  2. public static void main(String[] args) throws Exception {
  3. /*Person p = new Person("jzk",24,4);
  4. ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("lib\\Perosn.obj"));
  5. oos.writeObject(p);
  6. oos.close();*/  注释这里再次编译运行,就会出现老毕那种结果,如果直接一起呵成,就会出现static属性可以序列化的假象。
  7. ObjectInputStream ois = new ObjectInputStream(new FileInputStream("lib\\Perosn.obj"));
  8. Person pp = (Person)ois.readObject();
  9. System.out.println(pp);
  10. ois.close();
  11. }
  12. }

  13. class Person implements Serializable{

  14. private static final long serialVersionUID = 1L;
  15. private static int eyeNum = 2;
  16. transient private String name ;
  17. private int age;

  18. public Person() {}

  19. public Person(String name, int age ,int eyeNum) {
  20. this.name = name;
  21. this.age = age;
  22. this.eyeNum = eyeNum;
  23. }

  24. public String getName() {
  25. return name;
  26. }

  27. public void setName(String name) {
  28. this.name = name;
  29. }

  30. public int getAge() {
  31. return age;
  32. }

  33. public void setAge(int age) {
  34. this.age = age;
  35. }

  36. @Override
  37. public String toString() {
  38. return "Person [name=" + name + ", age=" + age + ", eyeNum=" + eyeNum + "]";
  39. }
  40. }
复制代码
我的猜测是:
静态属性是类共享的,所以Person类型变量pp与p共享一个 eyeNum,所以当p= new Person("jzk",24,4);时他们共享的eyeNum由2变为4,所以打印出来就是4,造成可以序列化的假象

但是,如果你注释了我上面程序中注释的那段代码,再次编译运行,就类似于重新启动了JVM,同时之前他们共享的eyeNum=4就丢失了,也只有这样才能证明静态属性eyeNum究竟有没有被序列化。

说的可能有点凌乱,希望你能看明白!

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1

查看全部评分

回复 使用道具 举报
额,没看懂………………
回复 使用道具 举报
transient 是什么意思?
回复 使用道具 举报
赵晓东 发表于 2013-4-14 16:24
transient 是什么意思?

transient是可以使非静态的变量也同样无序列化的,也就是说一个对象的序列化是根据其变量计算出来的,如果某个成员变量使用这个关键字,那么在计算其序列号的时候,这个变量是不会算进去的。

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1

查看全部评分

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马