Serializable--初解
一 序列化是干什么的?
我们知道,在jvm中引用数据类型存在于栈中,而new创建出的对象存在于堆中。如果电脑断电那么存在于内存中的对象就会丢失。那么有没有方法将对象保存到磁盘(对象持久化存储)或通过网络传输到远处的其他地方呢?
答案是可以,但是我们必须要求所有支持持久化存储的类实现Serializable接口。Serializable就像个通行证,只有持有这个通行证,jvm才让类创建的对象进行持久化。这个接口将类与一个称为serialVersionUID的变量关联起来,这个serialVersionUID就是在反序列化中用来确定由哪个类来加载这个对象。
二、什么情况下需要序列化
a)当你想把的内存中的对象状态保存到一个文件中或者数据库中时候;
b)当你想用套接字在网络上传送对象的时候;
c)当你想通过RMI传输对象的时候;
三、JavaBean为什么要实现java.io.Serializable接口实现序列化?
找了个比较好理解的例子:客户端访问了某个能开启会话功能的资源, web服务器就会创建一个与该客户端对应的HttpSession对象,每个HttpSession对象都要站用一定的内存空间。如果在某一时间段内访问站点的用户很多,web服务器内存中就会积累大量的HttpSession对象,消耗大量的服务器内存,即使用户已经离开或者关闭了浏览器,web服务器仍要保留与之对应的HttpSession对象,在他们超时之前,一直占用web服务器内存资源。
web服务器通常将那些暂时不活动但未超时的HttpSession对象转移到文件系统或数据库中保存,服务器要使用他们时再将他们从文件系统或数据库中装载入内存,这种技术称为Session的持久化。
将HttpSession对象保存到文件系统或数据库中,需要采用序列化的方式将HttpSession对象中的每个属性对象保存到文件系统或数据库中;将HttpSession对象从文件系统或数据库中装载如内存时,需要采用反序列化的方式,恢复HttpSession对象中的每个属性对象。所以存储在HttpSession对象中的每个属性对象必须实现Serializable接口。当然如果不是存储在session中的JavaBean可以不用存储哈。
举个简单例子:
Student
import java.io.Serializable; public class Student implements Serializable { /*serialVersionUID来决定由哪个类来加载存在于文件中的对象 * 如果指定serialVersionUID的数值,那就能使得其不再与类的成员变量相关联 * 不然你已经把对象保存到数据库,这个时候你再给这个对象新增属性,那么反序列化 * 就会报:本地类不匹配的错误,但如果指定serialVersionUID值那就不会报错。 */ private static final long serialVersionUID = -5182532647273106745L; //成员变量写成static的话是不能被持久化的 public static String countryName="china"; private String name; private int age; //如果想对非静态的数据也不想序列化,则需要加入关键字 transient String sex; /* 提供set和get方法,无参和有参方法*/ }
测试类
1 import java.io.*; 2 public class SerializableTest { 3 public static void main(String[] args) { 4 writeObj(); 5 readObj(); 6 } 7 public static void writeObj() 8 { 9 Student student=new Student("小筱", 1, "女"); 10 try { 11 ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("d:\\student.txt")); 12 oos.writeObject(student); 13 oos.close(); 14 } catch (IOException e) { 15 e.printStackTrace(); 16 } 17 } 18 public static void readObj() 19 { 20 try { 21 ObjectInputStream ooi=new ObjectInputStream(new FileInputStream("d:\\student.txt")); 22 try { 23 Object obj=ooi.readObject(); 24 Student student=(Student)obj; 25 System.out.println("age:"+student.getAge()+",name:"+student.getName()+",countryName:"+student.countryName+",sex:"+student.getSex()); 26 } catch (ClassNotFoundException e) { 27 e.printStackTrace(); 28 } 29 ooi.close(); 30 } catch (IOException e) { 31 e.printStackTrace(); 32 } 33 } 34 }
第二个小例子我没有亲自测试:用套接字在网络上传送对象
1.首先建立要传输的对象
1 //建立用来持续化的对象 2 import java.io.Serializable; 3 public class ObjectSeri implements Serializable{ 4 5 //成员变量写成static的话是不能被持久化的 6 //private关键字是不能被持久化的,脱离了JVM,成员变量是不在JVM的安全机制之内 7 private String name; 8 private String age; 9 /*set和get方法*/ <span style="color:#333333;"><strong> 10 </strong></span>
2.有了传输的对象,下一步就是建立一个服务端线程来监听socket端口,并且在run方法里面实现读取对象的数据
1 import java.io.IOException; 2 import java.io.ObjectInputStream; 3 import java.net.ServerSocket; 4 import java.net.Socket; 5 //serverTest类继承thread类,监听端口来的信息 6 public class serverTest extends Thread { 7 // private final String serverIP = "127.0.0.1"; 8 private final int serverPort = 3400; 9 private ServerSocket server; 10 public serverTest() { 11 try { 12 // ServerSocket server=new ServerSocket(serverPort); 13 server = new ServerSocket(serverPort); 14 System.out.println("正在监听3400端口"); 15 } catch (IOException e) { 16 e.printStackTrace(); 17 } 18 } 19 public void run() { 20 Socket socket = null; 21 ObjectInputStream in; 22 while (true) { 23 try { 24 synchronized (server) { 25 socket = server.accept(); 26 } 27 System.out.println("当前的连接是:" 28 + socket.getInetAddress().toString()); 29 socket.setSoTimeout(20000); 30 in = new ObjectInputStream(socket.getInputStream()); 31 ObjectSeri data = (ObjectSeri) in.readObject(); 32 System.out.println("The name is:" + data.getName() 33 + "and age is:" + data.getAge()); 34 in.close(); 35 in = null; 36 socket.close(); 37 } catch (IOException | ClassNotFoundException e) { 38 e.printStackTrace(); 39 } 40 } 41 } 42 public static void main(String args[]) { 43 (new serverTest()).start(); 44 }
3.最后,建立一个客户端来测试下
1 import java.io.ObjectOutputStream; 2 import java.net.InetSocketAddress; 3 import java.net.Socket; 4 //建立一个client测试类 5 public class TestClient { 6 private String address = "127.0.0.1"; 7 private int port = 3400; 8 9 public TestClient() { 10 // Prepare the data need to transmit 11 ObjectSeri data = new ObjectSeri(); 12 data.setName("Scott"); 13 data.setAge("34"); 14 Socket client = new Socket(); 15 InetSocketAddress adr = new InetSocketAddress(this.address, this.port); 16 try { 17 client.connect(adr, 10000); 18 ObjectOutputStream out = new ObjectOutputStream( 19 client.getOutputStream()); 20 // send object 21 out.writeObject(data); 22 out.flush(); 23 out.close(); 24 out = null; 25 data = null; 26 client.close(); 27 client = null; 28 } catch (java.io.IOException e) { 29 30 System.out.println("IOException :" + e.toString()); 31 } 32 } 33 public static void main(String[] args) { 34 new TestClient(); 35 } 36 } <span style="color: rgb(51, 51, 51);"> </span>
输出结果如下:
正在监听3400端口
当前的连接是:/127.0.0.1
The name is:Scottand age is:34
今天:2017:12:05 发现自己用到了,就是jquery表单提交,用post提交,这样有个最大的好处,就是我不用一个值一个值提交,而是把表单提交过去
$.post('your url', $("form").serialize(), function(data) { // your code } });
小筱的窝:水滴石穿,成功的速度一定要超过父母老去的速度! 少尉【2】