java序列化和反序列化
引语:????平时我们在运行程序的时候,创建的对象都在内存中,当程序停止或者中断了,对象也就不复存在了.如果我们能将对象保存起来,在需要使用它的时候在拿出来使用就好了,并且对象的信息要和我们保存
我们今天介绍的就是java原生的Serializable序列化. Serializable的使用序列化使用起来很简单只需要实现Serializable接口即可,然后序列化(序列化是将对象的状态信息转换为可以存储或传输的形式的过程)和反序列化(反之,从存储或传输形式还原为对象). private static void testSerializable(String fileName) throws IOException { try (ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(fileName))) { // "XXX" 的String也可以直接作为对象进行反序列化的 objectOutputStream.writeObject("test serializable"); SerializableData data = new SerializableData(1,"testStr"); objectOutputStream.writeObject(data); } } private static void testDeserializable(String fileName) throws IOException,ClassNotFoundException { try (ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(fileName))) { String str = (String) objectInputStream.readObject(); System.out.println("String的反序列化: " + str); SerializableData readData = (SerializableData) objectInputStream.readObject(); System.out.println("反序列化的对象: " + readData.toString()); // 输出:反序列化的对象: SerializableData(testInt=1,testStr=testStr) } } // 使用到的类 @Data @AllArgsConstructor class SerializableData implements Serializable { private Integer testInt; private String testStr; }
第一个方法是传入文件路径,将String和SerializableData对象序列化到fileName指定的文件中;第二个方法是反序列化将文件中的二进制还原为java对象. transient关键字简单的使用序列化和反序列化应该没有什么问题,我们再来看看transient关键字是啥?在某些场景下,我们需要写入或者还原的数据中其实有我们不需要透露或者说不想暴露给外部的数据,如果我们将这些隐私的数据序列化,在反序列化出来, private static void testTransient() throws IOException,ClassNotFoundException { String fileName = "transientData.txt"; try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(fileName))) { Account data = new Account(1,"user1","123456"); out.writeObject(data); } try (ObjectInputStream in = new ObjectInputStream(new FileInputStream(fileName))) { Account readData = (Account) in.readObject(); System.out.println("transient关键字的对象: " + readData.toString()); // 输出: transient关键字的对象: Account(id=1,userName=user1,idCardNumber=null) } } // 对应的对象 @Data @AllArgsConstructor class Account implements Serializable { private Integer id; private String userName; private transient String idCardNumber; }
这里我们有一个Account对象,我们不想暴露出我们的省份证号码idCardNumber,于是乎加上了transient关键字. Externalizable的使用使用过自动的序列化和反序列化以后,我们又想在序列化和反序列化的时候我们能不能自己控制呢?在序列化和反序列化的时候我们能不能加点日志或者其他的操作之类的呢? private static void testExternalizable() throws IOException,ClassNotFoundException { String fileName = "testExternalizable.txt"; try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(fileName))) { Account2 data = new Account2("user1",1); out.writeObject(data); } try (ObjectInputStream in = new ObjectInputStream(new FileInputStream(fileName))) { Account2 readData = (Account2) in.readObject(); System.out.println("Externalizable的对象: " + readData.toString()); } } // 使用到的对象 @Data @AllArgsConstructor class Account2 implements Externalizable { private Integer id; private String userName; private transient String idCardNumber; @Override public void writeExternal(ObjectOutput out) throws IOException { System.out.println("执行了writeExternal方法"); } @Override public void readExternal(ObjectInput in) throws IOException,ClassNotFoundException { System.out.println("执行了readExternal方法"); } }
如果执行了上面的代码,恭喜你,获得一个Exception的奖励.大概长这样,java.io.InvalidClassException:XXX no valid constructor, private static void testExternalizable() throws IOException,ClassNotFoundException { String fileName = "testExternalizable.txt"; try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(fileName))) { Account3 data = new Account3("user1",1); out.writeObject(data); } try (ObjectInputStream in = new ObjectInputStream(new FileInputStream(fileName))) { Account3 readData = (Account3) in.readObject(); System.out.println("Externalizable的对象: " + readData.toString()); /** * 输出: * 执行了writeExternal方法 * 执行了readExternal方法 * Externalizable的对象: Account3(userName=user1,id=1) */ } } @ToString class Account3 implements Externalizable { private String userName; private Integer id; public Account3() { } public Account3(String userName,Integer id) { this.userName = userName; this.id = id; } @Override public void writeExternal(ObjectOutput out) throws IOException { System.out.println("执行了writeExternal方法"); out.writeObject(userName); out.writeInt(id); } @Override public void readExternal(ObjectInput in) throws IOException,ClassNotFoundException { System.out.println("执行了readExternal方法"); userName = (String) in.readObject(); id = in.readInt(); } }
总结:1.我们介绍了jdk自带的序列化和反序列化(和其中的一些坑点);2.知道了transient可以将隐私数据不序列化;3.还有Externalizable可以自己来控制序列化和反序列化的进程. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |