Java序列化与反序列化
一.概述
1.序列化:是指将对象转化为二进制数据,保存到磁盘中
2.反序列化:将保存在磁盘中的二进制数据转化回对象。
3.作用:
1.将对象持久化,从内存中保存到磁盘,这次的分布式session需要缓存到redis服务器时进行序列化与反序列化。
2.当你想用套接字在网络上传送对象的时候。
二.怎么使用
1.首先,需要序列化的对象要实现Serializable接口,如图下。
public class Car implements Serializable{ private String name; private int id; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } }
2.建立序列化工具类,里面写序列化和反序列化的方法,如下:
//序列化的方法 public static Object DeserializeUser(byte b[]) { ByteArrayInputStream bis = null; ObjectInputStream ois = null; Object object=null; try { bis = new ByteArrayInputStream(b); ois = new ObjectInputStream(bis); object = ois.readObject(); } catch (Exception e) { e.printStackTrace(); } return object; } //反序列化的方法 public static byte [] SerializeUser(Object object) { ByteArrayOutputStream bos = null; ObjectOutputStream oos = null; byte b [] =null; try { bos = new ByteArrayOutputStream(); oos = new ObjectOutputStream(bos); oos.writeObject(object); b = bos.toByteArray(); }catch (Exception e) { } return b; }
3.写个测试类,新建一个Car,然后调用序列化工具类进行操作,成功,看下面:
四.异常处理
本来呢,出现这个问题去上网搜,发现是说在序列化时得到的字节数组并不是反序列化时的字节数组,他们出现问题的代码是这样的:图中在序列化完成后不应该用tostring,但是其实我在上面写的序列化工具类里面的方法是对的呀,就是在输出的时候使用toByteArray生成字节数组,反序列化的时候直接用这个数组
//序列化的方法 ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(bi); String str = baos.toString(); 错误的方法
byte[] str = baos.toByteArray(); 正确的方法 //反序列化
ObjectInputStream ois = new ObjectInputStream(new BufferedInputStream(new ByteArrayInputStream(str.getBytes())));//正确的这里应该直接用上面的字节数组。 Object obj = ois.readObject();
后来,仔细查找,还是发现原来在业务逻辑中出现了问题,业务中是这样的,序列化的时候返回的的确是正确的字节数组,但是由于要存到redis里面,又转为String,这个时候就错误了。下面是改正后用了jdk8的Base64工具类,就ok了。
//序列化
byte [] b = SerializUtil.SerializeUser(user);
//字节数组转String String serialize_user = Base64.getEncoder().encodeToString(b);
//反序列化
//String转字节数组
byte strData[] = Base64.getDecoder().decode(jedis.get(key));
User user = (User)SerializUtil.DeserializeUser(strData);