对象序列化Serializable

一、Java对象的存储

首先我们先来理解一下Java对象在内存中的存储!

JVM的内存分为三个部分:栈(stack)、堆栈(heap)、方法区(method area):

栈:主要存储基本数据类型变量、方法的形参、引用数据类型等;

堆栈:存储实例对象;

方法区:存储静态变量(静态常量池)、class信息等

如:当new出来一个对象后,对象的引用在栈中分配,指向堆中的实例对象;当局部对象变量使用完后,引用立即从栈中回收,堆中的对象等待GC回收;

再如:数组,在栈中分配数据名,堆中保存数据的大小和实例元素。

因此,java程序中的对象实例默认都是直接存储在内存中,一旦内存中被回收或意外丢失,将无法重构;

这就涉及到了java对象的序列化!

二:什么是对象序列化

在JavaBean的文章中曾提到,serializable的目的是类属性的持久化存储。比如需要开发MySQL的存储,那么将一条记录写入MySQL中的时候就需要实现Serializable接口。

那么到底什么是对象序列化呢?

对象序列化就是将对象实例的状态(是属性,不包括方法)保存到文件或者其它数据库,并且可以通过反序列化的方式对对象进行重构。

(对象序列化将内存中的变量实例(如JavaBean中的User bean)转换为二进制流,更加高效地在网络或存储介质上进行传输)

三:序列化示例

假设有如下类LoginUser,定义有username和password两个属性,main函数中创建了一个LoginUser对象,username值为50,password值为30;

然后将当前LoginUser对象的属性值保存到文件foo.ser中。

 1 import java.io.*;
 2 
 3 public class LoginUser {
 4     private String username;
 5     private String passwd;
 6     public String getUsername() {
 7         return username;
 8      }
 9     public void setUsername(String username) {
10         this.username = username;
11     }
12     public String getPasswd() {
13          return passwd;
14     }
15     public void setPasswd(String passwd) {
16         this.passwd = passwd;
17     }
18  
19 
20     public static void main(String[] args){   
21         LoginUser loginUser = new LoginUser();   
22         loginUser.setUsername("50");   
23         loginUser.setPasswd("30");   
24    
25         try{   
26             FileOutputStream fs = new FileOutputStream("foo.ser");   
27             ObjectOutputStream os =  new ObjectOutputStream(fs);   
28             os.writeObject(loginUser);   
29             os.close();   
30         }catch(Exception ex){   
31             ex.printStackTrace();   
32         }   
33     }  
34 
35 }                    

此时,运行该代码会出现如下异常:

1 java.io.NotSerializableException: com.longshine.zwp.test.LoginUser
2   at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1081)
3   at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:302)
4   at com.longshine.zwp.test.LoginUser.main(LoginUser.java:29)

提示找不到对应的序列化类型,需要对LoginUser类定义做出如下修改:

1 public class LoginUser implements Serializable{
2 
3 }

四、序列化注意事项

a)序列化时,只对对象的状态进行保存,而不管对象的方法;
b)当一个父类实现序列化,子类自动实现序列化,不需要显式实现Serializable接口;
c)当一个对象的实例变量引用其他对象,序列化该对象时也把引用对象进行序列化;

d)静态变量不能做序列化;

e)并不是所有的对象都能做序列化,比如Thread、socket等不能被序列化。

原文地址:https://www.cnblogs.com/yy20141204bb/p/10570366.html