黑马程序员技术交流社区

标题: ObjectOutputStream流中关于静态成员不能被序列化 [打印本页]

作者: 铁血丹心    时间: 2014-6-6 23:09
标题: ObjectOutputStream流中关于静态成员不能被序列化
我百度到的题目,我运行试了一下,也看不懂结果为什么?
第一种情况:先把readObj()注释掉,写入以后,再先把writer注释掉,然后再把readObj方法打开
writeObj();
//readObj();
然后再
//writeObj();
readObj();
输出结果:lisi--0--CN

第二种情况:两个都不注释同时运行
writeObj();
readObj();
输出结果:lisi--0--KR

输出结果为啥不一样???
第二种情况下,statci的 country 属性咋就变了呢
  1. package io.inputoutput;

  2. import java.io.*;

  3. class Person implements Serializable {
  4.         public static final long serialVersionUID = 42L;
  5.         String name;
  6.         transient int age; // 加 transient 关键字后的属性也不能被序列化
  7.         static String country = "CN"; // 静态的不能被序列化

  8.         Person(String name, int age, String country) {
  9.                 this.name = name;
  10.                 this.age = age;
  11.                 this.country = country;
  12.         }

  13.         public String toString() {
  14.                 return name + "--" + age + "--" + country;
  15.         }
  16. }

  17. public class ObjStream01 {
  18.         public static void main(String[] args) throws IOException,
  19.                         ClassNotFoundException {
  20.                 writeObj();
  21.                 readObj();
  22.         }

  23.         public static void writeObj() throws IOException { // 写入对象
  24.                 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(
  25.                                 "F:\\A\\123.txt"));
  26.                 oos.writeObject(new Person("lisi", 19, "KR"));
  27.                 oos.close();
  28.         }

  29.         public static void readObj() throws IOException, ClassNotFoundException { // 读取对象
  30.                 ObjectInputStream ois = new ObjectInputStream(new FileInputStream(
  31.                                 "F:\\A\\123.txt"));
  32.                 Person p = (Person) ois.readObject();

  33.                 System.out.println(p);
  34.                 ois.close();
  35.         }
  36. }
复制代码

作者: 彭飞    时间: 2014-6-7 00:29
本帖最后由 彭飞 于 2014-6-7 07:42 编辑

哥们:

情况是这个样子了。

首先明确,【静态变量是不能被序列化】的  但是为什么有发生了如此困惑的局面呢?

两个方法:  写、读。
writeObj();
readObj();

当单独写入后,再读取的时候 结果为:lisi--0--CN  ,情况正确、正常。
而两个方法同时运行时,结果为:lisi--0--KR    , 情况正确、正常。

哥们可能要杀人了。 哈哈。 原理在于内存中。

内存中有,栈、堆、方法区。  静态变量在方法区中,都知道。

当两个方法单独运行时,首先写入一个  new Person(1,2,3);>>>>  2和3,不被序列号,所以都变成了0和null   然后 toString()时,country  指向的是 cn
所以最后读取方法时,打印的结果是 cn。

而当 两个方都法运行时,按逻辑,应该也是一样的,执行写入完毕,读取。 但是问题来了,
同样是执行上面的步奏,当读的时候,
这个时候,写入的KR在内存中并没有立马消失,被  read  方法所识别,而read 方法中最先有的是 静态 country = cn ,
这个时候 就发生了,指向新的地址,最终序列化的时候变为了null,但toString 的时候就是 KR 了,

个人理解的是,首先我们走入了一个误区,昨夜久久不能入睡,忽然想到 老毕讲awt 用udp 实现在同一个 cmd 进行发送和读取信息
读写本不应该在一个线程中完成, 一个人自己说话的同时朗读,很容易产生混乱,搞不清的局面,
而线程正好就解决了这一问题,
好比哥们有俩电话,正在接电话的时候,另一电话又有妹纸找,哥们我接,跟这个妹纸说的时候,把另外的电话放远点,对吧,
一个人跟两个人说不着边际话,没问题。这也就是为什么 需要线程的缘故,


当然,这些都是我的推断。 这里有段小代码,仅供参考:
  1. package com.awt;

  2. import java.io.*;//Serializable;

  3. public class Test3 {
  4.         static String country = "CNn";//[1]、在方法区中就把地址给改变了。
  5.         public static void main(String [] args){
  6.                 String name = "a";
  7.                 int age = 1;
  8.                 //String country = "CNnttttt";//[2]、这个是编外,说明静态修饰 是优先初始化,但是 String 的特性没变。
  9.                 per p = new per(name,age,country);
  10.                 System.out.println(p);
  11.         }
  12. }
  13. class per{
  14.     String name;
  15.     transient int age;
  16.     static String country = "CN";
  17.    
  18.     per(String name, int age, String country) {
  19.             this.name = name;
  20.             this.age = age;
  21.             this.country = country;
  22.     }
  23.     public String toString() {
  24.             return name + "--" + age + "--" + country;
  25.     }
  26. }
复制代码


牵扯到以下三个问题:1、序列化问题       2、静态修饰问题       3、String特性问题     4、线程问题





作者: 谭荣强    时间: 2014-6-8 05:04
oos.writeObject(new Person("lisi", 19, "KR"));已经将country改成“KR(棒子!)”
两个方法不注释:
Proson类在内存中没有消失。当读取一个Person的实例对象时,静态被对象共享。所以打印KR.




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2