java序列化容易被忽略的面试题,程序员不服:工作还不是拧螺丝

什么是java序列化这种面试题相信大家都懂了,那么再稍微具体问下java对象哪些成员参与序列化,哪些不参与,怎么自定义序列化和反序列化过程?


java对象序列化

  1. 一般来讲,java对象可以序列化的是
  • 类名和属性,其中属性包含基本的数据类型,数组和引用的对象。

2.不可以序列化的内容

  • 类的方法。
  • 带static修饰的属性
  • 带transient修饰的属性

对象在序列化过程中要保留当前对象的数据,还会保存它引用到的对象数据,将这个层次结构写入字节流,这就是所谓的深复制了。整个过程中,如果有敏感信息的属性,例如密码,或者带个人隐私的属性,不需要在网络传递或者磁盘存储的,可定义为transient,这样,该字段就不会被序列化了,且该属性值只会保持初始化值。

代码举例

定义一个类Man,简单起见,就定义2个属性,name,和passwd

class Man implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private String transient passwd;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPasswd() {
return passwd;
}
public void setPasswd(String passwd) {
this.passwd = passwd;
}
public String toString(){
return "名字 :" + name + "密码:"+passwd;
}

对Man对象进行读操作

	private void read() {
FileInputStream fis = null;
ObjectInputStream ois = null;
try {
fis = new FileInputStream("d://man.txt");
ois = new ObjectInputStream(fis);
Man man = (Man) ois.readObject();
System.out.println("读取对象内容:" + man.toString());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
try {
fis.close();
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

写操作

private void write() {
FileOutputStream fos = null;
ObjectOutputStream oos = null;
try {
fos = new FileOutputStream("d://man.txt");
oos = new ObjectOutputStream(fos);
Man man = new Man();
man.setName("zhangsan");
man.setPasswd("123");
oos.writeObject(man);
oos.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fos.close();
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

运行代码

	public static void main(String[] args) {
App app = new App();
try {
app.write();
app.read();
} catch (Exception e) {
e.printStackTrace();
}
}

结果

读取对象内容:名字 :zhangsan密码:null,可见 通过transient 定义属性 就可以保证该属性不会序列化操作,从而显示初始值null。

自定义序列化过程

有时候密码等关键属性也要序列化,可以自定义序列化的过程,在这过程中可以加密一些信息。

在Man类重写writeObject()和readObject方法就行,例如我把密码写成123+“aaaaaaaaaaaaaaa”再序列化

private void writeObject(ObjectOutputStream out) throws IOException{
out.writeObject(name);
out.writeObject(passwd+"aaaaaaaaaaaaaaa");
}
private void readObject(ObjectInputStream in) throws Exception{
this.name = in.readObject().toString();
this.passwd = in.readObject().toString().replaceAll("aaaaaaaaaaaaaaa", "");
}

运行结果

读取对象内容:名字 :zhangsan密码:123,从而完成解密

写在最后

一般情况下,是不需要去自定义的,除非想做一些特殊的操作,例如加密,或者增加一些业务逻辑等,都可以使用上面方法进行自定义操作

发表评论
留言与评论(共有 0 条评论)
   
验证码:

相关文章

推荐文章

'); })();