(本内容是我在搜集一些资料后的个人感悟,如有问题,请指出。蟹蟹)
背景
对于Serializable,大家都知道是java中的一个接口
。用来标记是否可序列化,该接口中什么都没有。网上大部分都只是告诉我们,使用该接口可以使对象序列化,从而可以便于存储和传输。而如果不实现该接口,则在序列化的时候会抛出异常
。
(想自学习编程的小伙伴请搜索圈T社区,更多行业相关资讯更有行业相关免费视频教程。完全免费哦!)
疑问
读到这里或许有很多同学会产生疑问:
一个空接口,里面啥都没有。为什么java设计的时候一定要实现Serializable才能序列化?不能去掉Serializable这个接口,让每个对象都能序列化吗?
解答
笔者通过对网络上的答案进行浏览,虽然大部分都是解释Serializable的作用,没有说为什么要这样。但是最终还是找到一个比较有说服力的解释。
总的就是说安全性问题,具体原因见解释:假如没有一个接口(即没有Serializable来标记是否可以序列化),让所有对象都可以序列化。那么所有对象通过序列化存储到硬盘上后,都可以在序列化得到的文件中看到属性对应的值(后面将会通过代码展示)。所以最后为了安全性(即不让一些对象中私有属性的值被外露),不能让所有对象都可以序列化。要让用户自己来选择是否可以序列化,因此需要一个接口来标记该类是否可序列化。
证明
首先我们先建立一个person
类,该类有三个属性:一个年纪(我愿意告诉别人),一个姓名(我愿意告诉别人),一个秘密(我不愿意告诉别人)。具体代码如下。
public class Person implements Serializable {
private int age;
private String name;
//我的秘密
private String secret;
public Person(int age, String name, String secret) {
this.age = age;
this.name = name;
this.secret = secret;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Person() {
}
}
然后就是我们将这个Person的对象序列化存入硬盘啦。
public class Main {
public static void main(String[] args) {
/**
* person对象有三个属性,
* 一个是我的年纪(可以让别人知道)
* 一个是我的名字(可以让别人知道)
* 一个是我的秘密(我不想告诉别人)
*/
Person person = new Person(22, "小明", "我喜欢畅畅");
// 把对象存入硬盘
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person"));){
oos.writeObject(person);
} catch (IOException e) {
e.printStackTrace();
}
}
}
执行这段代码后,会在项目目录下发现一个person文件。然后大家会发现有些对象的值竟然是明文存在里面。
所有如果什么对象都可以序列化的话,那么对象的一些私有属性都有可能被恶意代码获取的阔能。所以呢,java设计人员为了安全起见,不允许所有的对象都能序列化,而是要用户编码的时候去指定可以序列化的类。
如果一个对象需要序列化,但是又有一些私密信息不想持久化呢?(例如单独将我们person的secret属性屏蔽持久化)
大家可以使用static或者transient修饰变量,具体怎么用呢?请移步happyjava同学的blog。
谢谢大家的阅读,以上是我个人看法,如有更多的看法可以评论一起交流。