java 中类为啥要序列化


java里为什么要序列化?
http://zhidao.baidu.com/link?url=7_wAQ8eAl28vcJPE5OKM5Y0Bo4aINNQokHhRmI9XPszEoTO5QF-gNbOTHPzU4e8JMxQ2FYFjU5kuUgtSIPYYN_
2013-06-19 09:57轻风晓雪 | 浏览 2276 次 编程语言java 1不序列化是二进制流,序列化也是二进制流,有什么不同?最后在计算机里不都是0和1保存嘛?还是说不序列化也可以恶保存,就是没有序列化保存的后好什么的? 2比如我写记事本里写了一篇文章,这里有对象吗?全都是文字啊,那我保存为文本文件的时候,也要序列化一下?然后我以后打开这个文本文件读取到内存,还要反序列化? 3比如实现购物信息记录的保存,不是要序列化吗,序列化以后保存的是文本文件还是什么文件,能用记事本打开看到文字的记录信息吗,不是说序列化后是字节流吗,那文本文件是字符流,那记录信息打开后应该是乱码才对啊,因为序列化后是字节流的!文本文件打开自然就是乱码了? 就不要说什么是序列化的概念什么了,我都看过好几遍了,说是为了保存对象结构什么的,但是还不是很理解,对于普通的字符串或者不序列化之间有何不同,还没明白,尽量用例子或者大白话给讲讲,不要太专业,通俗易懂就可以了 分享到: 2013-06-19 10:14 再不玩“疯狂攀岩”你就OUT啦! 提问者采纳 楼主的问题很有意思,不过你对序列化和反序列的应用场景搞错了,我们说的序列化和反序列化是对JAVA而言(其他面向对象语言可能也有)的,序列化的实体是个对象,结果也是个对象,并非是格式化文本,你在记事本里看到的购物信息保存记录,其实不是对象序列化的结果,而是对象输出的格式化文本,真正的序列化对象是看不懂的。 在实际使用对象序列化时,一种应用场景是将对象序列化到持久化存储(本地硬盘),我们此时不想做文件解析,也不想有人读懂这个持久化文件,当我们需要时,可以直接采用反序列化将保存的文件生成为对象;另一种应用场景是在网络传输过程中,此时对象会在不同主机上传播,序列化会将对象转成码流由对端进行解析,这个解析过程不需要人参与。 普通字符串是经过解析后的对象,有对象到字符串要加入解析逻辑,人才能看懂。 序列化的结果是个只有JAVA虚拟机认识的文件,人不参与,只是用于保存对象或传输。 解决你的问题了么? 追问: 序列化和购物信息记录里的字符串有关系吗?比如我不序列化,这些字就不能保存到硬盘了吗? 还一个就是序列化以后保存的对象在哪里啊,是购物信息记录里面的文字吗?都一起保存到硬盘上面了?还是放哪里,比如我打开购物信息记录里面只有:某某于某天购物等等,这里面哪有对象啊,跟看文本文件没区别啊,那咱们老说保存对象对象的 我不明白这个对象到底在哪里,和字符串有什么关系没 追答: 序列化和字符串没有关系。 字符串是对象里的某些数据的输出结果,你看到的文本文件只包含了对象的一部分信息,你看到可能只是个值而已。 比如一个对象 object monkey { String monkeyName = "悟空"; long monkeyAge = 1000; } 你输出的字符串可能只是这个: 悟空; 10000; 但对象很多信息丢掉了,比如对象名称,字段属性之类的。 序列化时把对象完整的输入到某个地方,比如文件,这个文件人类是看不懂的,但在反序列化时,文件就会被完成的读取为一个对象,和上面的对象一模一样,这样我们就可以在代码中对对象进行直接操作了。 are we clear? 追问: good!,原来如此,但是另一个问题又来了,对象保存在哪里?是跟我的文本文件一起保存到硬盘里吗?比如我的文本里字符串是5个字符串文字,按一个字符是2字节,大小是10字节,那如果按你的说法,把字段 名称也保持了,那文件的内容会增多,那有可能不是10字节了,因为你还保存了字段 属性名什么的,那岂不是多占我硬盘空间了? 追答: 保存在哪里是你控制的,你想输出到文件系统也可以,其他地方也行。 你说的大小我不知道跟什么比较,一般情况下肯定会比只保存字符串要大,毕竟有其他的信息需要存储。 会多占你些空间,但比起你手动反序列化这些成本还是值得的。 追问: 我的意思是说,你序列化以后保存的对象内容,是不是也在最终产生的文本文件里? 比如生成了一个购物信息记录.txt的文件,这里面假如有购物信息这4个文字,那对象能在文本里看到吗?还是只能看到字符串?保存的对象其实也在这个文件里,但是不会输出显示,而且最重要的是文件的大小在电脑里还是显示4个字符的大小,但是对象它也是存在的也占硬盘空间,只不过系统只显示字符串的大小而已? 追答: 文本文件是用来保存文本的,是你在代码里控制生成txt。 对象序列化生成的序列化文件,跟txt文件没有关系,你序列化之后存成什么样的文件格式,存储到什么位置,是自己控制的。 你不应该认为txt存储对象,txt存储的只能是文本,对象序列化的结果是一个序列化文件,是一个文件输出流的结果。 追问: 序列化文件保存在哪,我想见识见识,保存在电脑的哪个角落里?我看看跟文本文件有啥不一样的 追答: import java.io.Serializable; import java.io.*; public class Cat implements Serializable { private String name; public Cat() { this.name = "new cat"; } public String getName() { return this.name; } public void setName(String name) { this.name = name; } public static void main(String[] args) { Cat cat = new Cat(); try { FileOutputStream fos = new FileOutputStream("catDemo.out"); //这就是你序列化文件的存储位置,是由自己控制的 ObjectOutputStream oos = new ObjectOutputStream(fos); System.out.println(" 1> " + cat.getName()); cat.setName("My Cat"); oos.writeObject(cat); oos.close(); } catch (Exception ex) { ex.printStackTrace(); } try { FileInputStream fis = new FileInputStream("catDemo.out"); ObjectInputStream ois = new ObjectInputStream(fis); cat = (Cat) ois.readObject(); System.out.println(" 2> " + cat.getName()); ois.close(); } catch (Exception ex) { ex.printStackTrace(); } } } 输出内容: catDemo.out大小:0.06K 已经过百度安全检测,放心下载 点击下载 下载量:53 追问: 原来.out文件就是序列化后的文件啊,那保存的购物信息记录也全在这里面吗?如果是在这里,那这个文件不是.txt格式的,打开看肯定是乱码? 如果信息记录没在out文件里,那应该在指定一个路径保存为.txt文件格式吧?这个就是能打开看的信息记录? 这俩文件是分开的 还是合在一起的? 追答: 保存的购物信息都在catDemo.out中,但你是看不懂的,要JAVA虚拟机才能看懂,因为序列化文件本身不是为人类阅读准备的。 如果你想输出为txt,需要你在程序中手动指定输出的内容和格式,这样你才能够看懂。 不是两个文件,也可能是多个文件,你想生成多少文件就生成多少文件。 追问: 那在问下,如果我也想保存输出为txt格式的。在程序中手动添加一个路径为:购物信息.txt就行了是吗?那你上面的那个catDemo.out不用删掉继续保留? 这样在电脑里就会产生一个是catDemo.out文件,一个是文本格式的购物信息.txt? catDemo.out已经是序列化保存了一次了,后面再输出的.txt不需要序列化了,直接输出字符流保存到电脑里即可?因为前面已经有一个序列化了 追答: 对的,你可以这样理解。 另外你是否需要序列化看你自己的需求,序列化是为了程序读取方便,没有必要非得输出的。 追问: 意思就是说,你要不序列化也行,就是程序读取不方便,而且以前在内存里的对象结构全都没有了? 上面那个还要问下,其实在catDemo.out文件里只包含对象信息,应该也包含字符串信息吧?就是应该也包含txt里面的购物信息,而我输出txt格式,只是从catDemo.out文件里提取出字符串部分的信息给用户看而已,实际对象内容还在catDemo.out里保存? 追答: 序列化是一种操作,你做序列化不是必要的,你做序列化是因为你想保存这个对象在文件系统上。 想象一种场景: 你开发了一个游戏,游戏里有人物,人物里有个属性时他现在拥有的金钱,当用户玩到一半选择保存游戏时,你有两个方案: 保存用户的金钱到txt中,下次加载游戏的时候,再从txt中读取金钱,让用户接着玩。 进行对象序列化,把对象存到文件系统上,下次可以玩的时候使用反序列化加载。 但是第一种方案有个缺点,用户如果知道了txt中保存着金钱,就可以自己把金钱改成99999,采用对象序列化方式就不会了。 最后一个,你没有理解JAVA中的对象,对象是在内存中保存的,它不会因为你序列化了之后它就不存在了,序列化等于把对象的数据复制了一份,序列化,然后输出到文件系统,真正的对象还是在程序中的。 就像你玩游戏玩到一半,突然想存个档,然后就把对象序列化了,但是游戏还在继续啊,里面的人物也没死啊,说明人这个对象还是在内存中存在的。 are we clear? 提问者评价 谢谢! 评论(11) | 77 0 babyly1314 | 四级 采纳率71% 擅长: 电脑装机/选购 JAVA相关 服务器软件 架构设计 汽车购买 其他类似问题 2010-08-14什么是java序列化,如何实现java序列化?18 2010-12-06java中为什么要序列化?什么时候序列化。42 2012-02-19Java中为什么要序列化?什么时候用到序列化?61 2008-05-13关于java序列化的问题27 2010-12-22什么是序列化,在java中如何实现序列化。40 更多关于java 中类为啥要序列化的问题>> 2013-06-19 10:23 网友采纳 你知道什么叫 序列化 吗? 你知道序列化的作用吗? 你可以把序列化,实现Serializable 接口,是序列化了的类告知该程序,这个类的对象可以读写。 读写不仅仅是在文本中读写该类,还可以通过别的流来进行读写。 没有序列化的类,是不能形成二进制读写流。 如果你随便敲写文字进去一个记事本里面。这个就不是序列化的范围了。序列化是指类对象的。你能确保你自己敲上去的文字就是类的对象了吗?你能确保你敲上去的是什么类的对象吗? 第三个问题,已经没有必要解释了。你要知道序列化是什么东西,你就不会问这问题 评论 | 3 4 Stale331x | 来自团队:Java乐园 | 十级 采纳率47% 擅长: JAVA相关 数据结构及算法 数据库DB 服务器软件 为您推荐: 按默认排序 | 按时间排序 其他3条回答 2013-06-19 10:31 zqhmfk | 五级 要使得javabean能够通过I/O在网络传输那么就必须实现Serializable接口,这是一种规范,就相当于你要tomcat调用你的servlet你必须实现它的接口一样。 要解释你的疑问就说说流吧: 首先流分为:字节流(Inputstream)、字符流(Reader),而你说的文件那就属于FileInputStream属于字节流,而你说的对象那就是ObjectInputStream也属于字节流,但是写对象必须实现Serializabled接口(这是API文档原话:只能将支持 java.io.Serializable 接口的对象写入流中。每个 serializable 对象的类都被编码,编码内容包括类名和类签名、对象的字段值和数组值,以及从初始对象中引用的其他所有对象的闭包。) 追问: FileInputStream属于字节流,这也是字节流,是不是说如果我保存的不是对象,可以用这个流?可是java里好像都有对象啊,那就都只能用ObjectInputStream流? 那保存的购物记录是文本文件啊,打开能看到里面的文字信息,也没看到有对象啊,那序列化保存的对象在哪里啊,也在购物记录里吗,一起保存到硬盘里去了? 追答: 文本文件属于字符流(Reader),让你看下API文档原话你就明白了:FileReader 用于读取字符流。要读取原始字节流,请考虑使用 FileInputStream。 大哥还在纠结啊。。。 我最后就给你讲一个大家熟悉的一个例子 大家都用过web容器吧,现在就说weblogic 假如我们要去注册帐号,我们是先进入注册页面,把必填的都填完,最后点击注册按钮ok 此时客户端就发送了一个request注册的请求, 1客户端先把用户填写的信息保存在该请求中-------------------------------客户端 2然后把该请求request对象序列化,request对象保存了用户填写的注册信息 Socket socket=new Socket("ip",10000); ObjectOutputStream oos1 = new ObjectOutputStream(socket.getOutputStream()); FileOutputStream out = new FileOutputStream("file.object"); //楼主看看跟文本文件有啥不一样的ObjectOutputStream oos2 = new ObjectOutputStream(out); oos1.writeObject(request); //楼主要看序列化是怎么样的加这句 oos2.writeObject(request); oos.close(); 3然后服务器也就是weblogic接收该请求,进行反序列化-----------------------------服务器 ServerSocket ss=new ServerSocket(10000); while(true){ socket=ss.accept(); ObjectInputStream ois = new ObjectInputStream(socket.getInputStream()); Request request= (Request) ois.readObject(); ois.close(); } 写的好累啊。。。望楼主采纳!!! 评论 | 4 0 2013-06-19 10:11 testhdg | 四级 以前我也不理解,不过现在我已经理解了: 是这样的,如果JAVA的对象要保存到硬盘或者要传输,必须实现Serializable接口,则这个接口,里面什么方法都没,它只是一个标识,而且,最好有一个序列的版本号,如private static final long serialVersionUID = 1L;以前我做过实验,我写了一个类Person,然后Person p=new Person();通过序列化,我用代码把p这个对象,保存在文件文件里了!不序列化,绝对不可能保存在计算机硬盘里! 追问: 那文本文件打开后是不是只能看到字符串,看不见保存的对象信息?但是这个文件里面确实有对象信息,只不过系统不给你显示出来,只显示字符串内容而已?而且这个文件实际大小应该是字符串大小+对象大小,但是系统一样只显示文本信息的字符串大小? 是这么理解吧? 追答: 我用代码把p这个对象,保存在文件文件里后,打开看了,不像乱码,但又像乱码的东西。你说得对,只能看到字符串,看不见保存的对象信息,但,你用代码处理后,就可以看见保存的对象信息了。要自己写代码处理,当初怎么写,就反过来,就可以显示对象的信息了。大小与你的对象个数有关,我那时也做了试验,我循环写10与10000次,大小就不一样了。文件大小,不好说,应该只与对象有关,哪来的什么字符串。代码是别人帮我写字,但忘记在哪了,不然,贴出来给你,你就理解了。

序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化。可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间。序列化是为了解决在对对象流进行读写操作时所引发的问题。序列化的实现:将需要被序列化的类实现Serializable接口,该接口没有需要实现的方法,implements Serializable只是为了标注该对象是可被序列化的,然后使用一个输出流(如:FileOutputStream)来构造一个ObjectOutputStream(对象流)对象,接着,使用ObjectOutputStream对象的writeObject(Object obj)方法就可以将参数为obj的对象写出(即保存其状态),要恢复的话则用输入流。  
序列化:序列化是将对象转换为容易传输的格式的过程。例如,可以序列化一个对象,然后使用 HTTP 通过 Internet 在客户端和服务器之间传输该对象。在另一端,反序列化将从该流重新构造对象。 
是对象永久化的一种机制。 
   确切的说应该是对象的序列化,一般程序在运行时,产生对象,这些对象随着程序的停止运行而消失,但如果我们想把某些对象(因为是对象,所以有各自不同的特性)保存下来,在程序终止运行后,这些对象仍然存在,可以在程序再次运行时读取这些对象的值,或者在其他程序中利用这些保存下来的对象。这种情况下就要用到对象的序列化。 
   只有序列化的对象才可以存储在存储设备上。为了对象的序列化而需要继承的接口也只是一个象征性的接口而已,也就是说继承这个接口说明这个对象可以被序列化了,没有其他的目的。之所以需要对象序列化,是因为有时候对象需要在网络上传输,传输的时候需要这种序列化处理,从服务器硬盘上把序列化的对象取出,然后通过网络传到客户端,再由客户端把序列化的对象读入内存,执行相应的处理。 
   对象序列化是java的一个特征,通过该特征可以将对象写作一组字节码,当在其他位置读到这些字节码时,可以依此创建一个新的对象,而且新对象的状态与原对象完全相同。为了实现对象序列化,要求必须能够访问类的私有变量,从而保证对象状态能够正确的得以保存和恢复。相应的,对象序列化API能够在对象重建时,将这些值还原给私有的数据成员。这是对java语言访问权限的挑战。通常用在服务器客户端的对象交换上面,另外就是在本机的存储。 
   对象序列化的最主要的用处就是在传递,和保存对象(object)的时候,保证对象的完整性和可传递性。譬如通过网络传输,或者把一个对象保存成一个文件的时候,要实现序列化接口

原文地址:https://www.cnblogs.com/wzhanke/p/4766651.html