Serializable接口和transient关键字
1. 什么是Serializable接口?
当一个类实现了Serializable接口(该接口仅为标记接口,不包含任何方法),表示该类可以被序列化。
序列化的目的是将一个实现了Serializable接口的对象转换成一个字节序列, 可以将该字节序列保存起来(如:保存在一个文件中),以后可以随时将该字节序列恢复为原来的对象。甚至可以将该字节序列放到其他计算机上或者通过网络传输到其他计算机上恢复,只要该计算机平台存在相应的类。
2. 如何实现?
首先创建一个OutputStream对象,然后将其封装在一个ObjectOutputStream对象内,再调用writeObject()方法即可序列化一个对象。反序列化也类似。
import java.io.*;
public class Person implements Serializable {
private String userName;
private String password;
public Person(String userName, String password) {
this.userName = userName;
this.password = password;
}
public String toString() {
return "userName:" + userName + " password:" + password;
}
public static void main(String[] args)
throws FileNotFoundException, IOException, ClassNotFoundException {
//序列化一个对象(存储到一个文件)
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person.out"));
oos.writeObject("Save a object:\n");
oos.writeObject(new Person("Bruce", "123456"));
oos.close();
//反序列化,将该对象恢复(存储到一个文件)
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person.out"));
String s = (String)ois.readObject();
Person p = (Person)ois.readObject();
System.out.println(s + p);
//序列化一个对象(存储到字节数组)
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos2 = new ObjectOutputStream(baos);
oos2.writeObject("Save another object:\n");
oos2.writeObject(new Person("Phil", "654321"));
oos2.close();
//反序列化,将该对象恢复(存储到字节数组)
ObjectInputStream ois2 = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()));
s = (String)ois2.readObject();
p = (Person)ois2.readObject();
System.out.println(s + p);
}
}
输出信息:
Save a object:
userName:Bruce password:123456
Save another object:
userName:Phil password:654321
3. transient关键字:
1)引入原因:自动序列化将对象所有的字段都持久化了,有的时候需要对某些字段不进行持久化(例如:密码,因为序列化后会暴露密码),所以我们使用transient关键字让Serializable对象某些字段不被序列化。
2)操作:
public class Person implements Serializable{
private String userName;
// 不序列化password——因为序列化后会暴露密码
private transient String password;
}
加入transient关键字后,上面程序的运行结果:
Save a object:
userName:Bruce password:null
Save another object:
userName:Phil password:null
3)如果想要控制序列化字段,使得被transient修饰的字段也能被序列化:有两种方法
1. 手动序列化,添加两个私有的方法:writeObject(),readObject()
import java.io.*;
public class Person implements Serializable {
private String userName;
private transient String password;
public Person(String userName, String password) {
this.userName = userName;
this.password = password;
}
public String toString() {
return "userName:" + userName + " password:" + password;
}
private void writeObject(ObjectOutputStream out) throws IOException {
//序列化所有非transient字段,必须是该方法的第一个操作
out.defaultWriteObject();
//序列化transient字段
out.writeObject(password);
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
//反序列化所有非transient字段,必须是该方法的第一个操作
in.defaultReadObject();
//反序列化transient字段
password = (String)in.readObject();
}
public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
//序列化一个对象(存储到一个文件)
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person.out"));
oos.writeObject("Save a object:\n");
oos.writeObject(new Person("Bruce", "123456"));
oos.close();
//反序列化,将该对象恢复(存储到一个文件)
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person.out"));
String s = (String)ois.readObject();
Person p = (Person)ois.readObject();
System.out.println(s + p);
}
}
输出结果:
Save a object:
userName:David password:13579
2. 使用Externalizable接口替代Serializable接口。
- 此时需要定义一个默认的构造器,否则将会得到一个异常:(java.io.InvalidClassException: Person; Person; no valid constructor);
- 还需要定义两个方法(writeExternal()和readExternal())来控制要序列化的字段
import java.io.*; //使用Externalizable接口代替Serializable接口
public class Person implements Externalizable {
private String userName;
private String password; // 需要一个默认的构造器,否则得到一个异常
public Person() {
System.out.println("default constructor invoked!");
} public Person(String userName, String password) {
this.userName = userName;
this.password = password;
} public String toString() {
return "userName:" + userName + " password:" + password;
} public void writeExternal(ObjectOutput out) throws IOException {
//序列化字段
out.writeObject(userName);
out.writeObject(password);
} public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
//反序列化字段
userName = (String)in.readObject();
password = (String)in.readObject();
} public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
/ /序列化一个对象(存储到一个文件)
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person.out"));
oos.writeObject("Save a object:\n");
oos.writeObject(new Person("Leo", "1984"));
oos.close(); //反序列化,将该对象恢复(存储到一个文件)
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person.out"));
String s = (String)ois.readObject();
Person p = (Person)ois.readObject();
System.out.println(s + p);
}
}
得到结果如下:
default constructor invoked!
Save a object:
userName:Leo password:1984
注意:
Serializable接口和transient关键字的更多相关文章
- Java中的Serializable接口和transient关键字
Java中的Serializable接口和transient关键字 Table of Contents 1. 向memcached中放数据时遇到NotSerializableException异常 2 ...
- Java中的实体类--Serializable接口、transient 关键字
在java中,实体类是一个非常重要的概念,我们可以在实体类中封装对象.设置其属性和方法等.关于实体类,也经常涉及到适配器模式.装饰者模式等设计模式.那么在实际代码开发中,关于实体类的注意事项有哪些呢? ...
- Java的transient关键字
Java的transient关键字 Java 中的 transient 关键字被用来表示变量将不被序列化处理.那么在理解 transient 关键字之前,我们先了解下什么是序列化. 什么是序列化 ...
- Java Serializable的使用和transient关键字使用小记(转载)
一:Serializable 1.持久化的简单介绍: “持久化”意味着对象的“生存时间”并不取决于程序是否正在执行——它存在或“生存”于程序的每一次调用之间.通过序列化一个对象,将其写入磁盘,以后在程 ...
- transient关键字的用法
本篇博客转自 一直在路上 Java transient关键字使用小记 1. transient的作用及使用方法 我们都知道一个对象只要实现了Serilizable接口,这个对象就可以被序列化,Java ...
- Java transient关键字使用小记
哎,虽然自己最熟的是Java,但很多Java基础知识都不知道,比如transient关键字以前都没用到过,所以不知道它的作用是什么,今天做笔试题时发现有一题是关于这个的,于是花个时间整理下transi ...
- Java transient关键字序列化时使用小记
1. transient的作用及使用方法 我们都知道一个对象只要实现了Serilizable接口,这个对象就可以被序列化,java的这种序列化模式为开发者提供了很多便利,我们可以不必关系具体序列化的过 ...
- Java 序列化 transient关键字
Java 序列化 transient关键字 @author 敏敏Alexia 转自:http://www.cnblogs.com/lanxuezaipiao/p/3369962.html 1. tra ...
- (转)Java transient关键字使用小记
背景:最近在看java底层的源码实现,看到一个关键字,不是很熟悉,专门做个记录. 原文出处:http://www.importnew.com/21517.html#comment-637072 哎,虽 ...
随机推荐
- peer not authenticated error
问题背景 系统:OS X El Capitan,10.11.2 IDE:Android Studio 2.0 Preview Java:1.8.0_65 Gradle:2.3 clone了代码后,在i ...
- UML6大关系
1.继承关系(inherit) 空心三角+实线 2.实现(接口)关系 空心三角+虚线 3.聚合关系(Aggregation,弱拥有,A对象可以包含B对象,但B对象不是A的一部分) 空心菱形+实线箭头 ...
- Build subversion 1.8 with SSL on OS X Yosemite
mkdir -p /tmp/buildroot && cd /tmp/buildroot # Need to build the latest libtool and automake ...
- (windows)mongoDB3X+Robomongo的安装与基础配置
一开始安装的时候还觉得很简单真正装了时候发现网上的资料参差不齐再次整理一份安装方法 ---------------------------------------------------------- ...
- JS数组push会覆盖前面的数据问题
这是一个作用域和重新赋值的问题. 检查声明数组所在位置,特别在是多层嵌套中,检查是否在内层循环结束时 跳到外层循环就重新将 数组 赋值为空.
- Android IOS WebRTC 音视频开发总结(七八)-- 为什么WebRTC端到端监控很关键?
本文主要介绍WebRTC端到端监控(我们翻译和整理的,译者:weizhenwei,校验:blacker),最早发表在[编风网] 支持原创,转载必须注明出处,欢迎关注我的微信公众号blacker(微信I ...
- 读取excel数据,并统计输出Frame版本
package cn.cnnic.ops; import java.awt.Button; import java.awt.FileDialog; import java.awt.FlowLayout ...
- visual studio code(vscode) 调试php(转)
原文链接:http://www.cnblogs.com/CLR010/p/5276077.html visual studio code(vscode) 调试php 1.下载vscode (vis ...
- XidianOJ 1041: Franky的游戏O
题目描述 Franky是super的人造人,来到了n*m的棋盘世界玩冒险游戏. n×m的棋盘由n行每行m个方格组成,左上角的方格坐标是(0,0),右下角的方格坐标是(n-1,m-1). 每次游戏时,他 ...
- Linux不使用useradd创建用户
手动创建用户的全过程:需要管理员权限. 1.在/etc/group中添加用户所属组的相关信息.如果用户还有辅助组则在对应组中加入该用户作为成员. 2.在/etc/passwd和/etc/shadow中 ...