1.什么是序列化?
把Java对象转换为字节序列的过程称为对象的序列化,把字节序列恢复为Java对象的过程称为对象的反序列化。
对象的序列化主要有如下2种用途:
- 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中
- 在网络上传送对象的字节序列
2.序列化的实现方式
- 类继承Serializable接口,可使用writeObject方法和readObject方法控制类序列化的过程。 默认情况下只会初始化化非transient得实例变量。 一般使用writeObject方法和readObject方法来优化序列化的过程或者对敏感数据进行特殊的处理。
package com.wilian.serialize; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.Date; import java.util.List; /** * * @author wilian * */ //通过实现Serializable接口实现序列化 public class Comsumer implements Serializable { private static final long serialVersionUID = -6701934960639960628L; public static int MAX_BILL =2000; private String name; private Date birthday; private transient String password; private List<Order> orders; static{ //反序列化不会调用静态初始化块 System.out.println("静态初始化块"); } public Comsumer() { //反序列化不会构造方法 System.out.println("正在创建一个Comsumer"); } public String getName() { return name; } public void setName(String name) { this.name = name; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public List<Order> getOrders() { return orders; } public void setOrders(List<Order> orders) { this.orders = orders; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } private void writeObject(ObjectOutputStream out) throws IOException{ out.defaultWriteObject(); out.writeObject(this.password); } private void readObject(ObjectInputStream in)throws IOException, ClassNotFoundException{ in.defaultReadObject(); this.password=(String)in.readObject(); } }
package com.wilian.serialize; import java.io.Serializable; //通过实现Serializable接口实现序列化 public class Order implements Serializable{ private static final long serialVersionUID = -4383674802849314614L; private String orderNo; private int money; public String getOrderNo() { return orderNo; } public void setOrderNo(String orderNo) { this.orderNo = orderNo; } public int getMoney() { return money; } public void setMoney(int money) { this.money = money; } }
package com.wilian.serialize; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.util.ArrayList; import java.util.Date; import java.util.List; public class SerializedTest { public static void main(String[] args) { ObjectOutputStream oos =null; ObjectInputStream ois =null; try { FileOutputStream fos = new FileOutputStream( new File("D://cumsumer.dat")); oos = new ObjectOutputStream(fos); Comsumer comsumer= new Comsumer(); comsumer.setBirthday(new Date()); comsumer.setName("wilian"); comsumer.setPassword("12345678"); List<Order> orders=new ArrayList<Order>(); Order order1 = new Order(); order1.setMoney(15); order1.setOrderNo("001"); orders.add(order1); Order order2 = new Order(); order2.setMoney(19); order2.setOrderNo("002"); orders.add(order2); comsumer.setOrders(orders); oos.writeObject(comsumer); FileInputStream fis = new FileInputStream( new File("D://cumsumer.dat")); ois=new ObjectInputStream(fis); Comsumer c =(Comsumer) ois.readObject(); //验证两个对象是否相等 System.out.println(comsumer==c); System.out.println(comsumer.equals(c)); // System.out.println(c.getName()); System.out.println(c.getBirthday()); System.out.println(c.getPassword()); System.out.println(c.getOrders().size()); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); }finally{ if(oos!=null) try { oos.close(); } catch (IOException e) { e.printStackTrace(); } if(ois!=null) try { ois.close(); } catch (IOException e) { e.printStackTrace(); } } } }
- 实现Externalizable接口;Externalizable接口继承自Serializable接口,可以完全控制类的序列化行为。与Serializable另外个不同之处:一个类如果实现了Externalizable接口,那么它必须具有public类型的不带参数的构造方法,否则这个类无法反序列化。
package com.wilian.serialize; import java.io.Externalizable; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectInputStream; import java.io.ObjectOutput; import java.io.ObjectOutputStream; import java.util.Date; public class Dog implements Externalizable { protected String name; protected int weight; protected Date birthday; public Dog(String name, int weight, Date birthday) { this.name = name; this.weight = weight; this.birthday = birthday; } //要提供public无参构造方法否则会抛出如下异常 //java.io.InvalidClassException: com.wilian.serialize.Dog; no valid constructor public Dog(){}; @Override public void writeExternal(ObjectOutput out) throws IOException { out.writeObject(name); out.writeInt(weight); out.writeObject(birthday); } @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { name=(String)in.readObject(); weight=in.readInt(); birthday=(Date)in.readObject(); } public static void main(String[] args) { try { FileOutputStream fos = new FileOutputStream( new File("D://dog.dat")); ObjectOutputStream oos = new ObjectOutputStream(fos); Dog dog=new Dog("Wangcai",25,new Date()); oos.writeObject(dog); oos.close(); FileInputStream fis = new FileInputStream( new File("D://dog.dat")); ObjectInputStream ois = new ObjectInputStream(fis); Dog dog1 =(Dog) ois.readObject(); ois.close(); System.out.println(dog1.name); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } } }
3.序列化中readResolve()方法的应用
由上面的例子可以看出序列化出来的对象与序列化之前的对象非同一个对象,如果在有些单例的场景这样就违反了JVM中只有一个实例的约定。如果一个类提供了readResolve方法,那么在执行反序列化操作时,先按照默认方式或者用户自定义的方式进行反序列化,最后再调用readResolve方法,该方法返回的对象为反序列化的最终结果。
package com.wilian.serialize; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.ObjectStreamException; import java.io.Serializable; public class SystemConfig implements Serializable { /** * */ private static final long serialVersionUID = 4026591699359366802L; private static final SystemConfig instance =new SystemConfig(); private String ip; private String host; private int port; private SystemConfig(){ this.ip="127.0.0.1"; this.host="localhost"; this.port=8080; } public static SystemConfig getInstance(){ return instance; } public String getIp() { return ip; } public String getHost() { return host; } public int getPort() { return port; } /** * 返回值必须是Object,否则函数不生效 * 方法权限可以是private\默认\protected级别 * @return Object * @throws ObjectStreamException */ private Object readResolve() throws ObjectStreamException{ return instance; } public static void main(String[] args) { try { SystemConfig config=SystemConfig.getInstance(); ByteArrayOutputStream buf = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(buf); oos.writeObject(config); ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(buf.toByteArray())); SystemConfig config1 = (SystemConfig)ois.readObject(); System.out.println(config1==config); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } } }
4.serialVersion序列化版本的作用
serialVersionUID有两种用途:
- 希望不同版本对序列化兼容,因此需要确保类的不同版本具有相同的seriaVersionUID;
- 不希望不同版本对序列化兼容,因此需要确保类的不同版本具有不同的seriaVersionUID;
当一个类的不同版本的seriaVersionUID相同,仍然有可能出现序列化不兼容的情况。
相关推荐
java序列化(Serializable)的作用和反序列化.doc 有详细的讲解哦。 在什么地方用的到都有说明的.
java 序列化详细解释 很详细 适用于高级软件开发者
java序列化代码示例,详细讲解序列化作用于使用注意规则项!!!
Java SE编程入门教程 java序列化(共14页).pptx Java SE编程入门教程 java异常(共57页).pptx Java SE编程入门教程 java正则(共8页).pptx Java SE编程入门教程 properties(共3页).pptx Java SE编程入门教程 ...
序列化是干什么的? 简单说就是为了保存在内存中的各种对象的状态(也就是实例...虽然你可以用你自己的各种各样的方法来保 存object states,但是Java给你提供一种应该比你自己好的保存对象状态的机制,那就是序列化。
大家请看Java的序列化结构有不足的地方请指教也希望指出不足的地方。
java序列化和反序列化java序列化和反序列化java序列化和反序列化
将java数据 序列化成PHP的格式 a:4:{s:6:"title2";s:13:"这是标题2";s:6:"title3";s:13:"这是标题3";s:5:"title";s:13:"这是标题1";s:6:"title4";s:13:"这是标题4";} 或者a:1:{i:0;a:1:{s:4:"name";s:10:"这是1321";...
在应用java进行c-s开发的时候,尤其涉及到图片和视频之间的传输时,需要用序列化和反序列化技术,希望对您有帮助
该资源提供了java常见的三个序列化框架,分别是:JBoss Marshalling,messagePack,protobuf-java
07-Java序列化面试题(10题)-新增
java 序列化,java 序列化,java 序列化,java 序列化,java 序列化,java 序列化
NULL 博文链接:https://hw1287789687.iteye.com/blog/2190768
E043-服务漏洞利用及加固-利用Java序列化漏洞进行渗透测试
java序列化是面试中经常涉及的重要主题之一。对Java序列化的深入了解不仅可以展示你的编程技能,还能体现出你对Java核心概念的掌握。本文精选了20道复杂的Java序列化面试题,并提供了详细的解析,旨在帮助你更好地...
Java序列化与反序列化 Java序列化与反序列化 Java序列化与反序列化 Java序列化与反序列化 Java序列化与反序列化
Java序列化机制(2)- serialVersionUID 实验 http://blog.csdn.net/suileisl/article/details/16991753
android(包括java)序列化一个对象传给php去做处理,或是接到php的序列化的对象在java中做处理的工具jar包以及使用方法. 使用方法: byte[] b = null; b = PHPSerializer.serialize(一个对象);//将一个对象序列化后返回...
详细讲解了java的序列化用处、原理、算法、如何实现。希望能帮到大家。