马桶🚽Java 上厕所就能看完的小知识! 欢迎关注、点赞 持续更新!
我们都知道,在学习对象序列化反序列化的时候都需要实现一个Serializable
接口
可是我们点进去一看,这个接口长这个样子
/
* @author unascribed
* @see java.io.ObjectOutputStream
* @see java.io.ObjectInputStream
* @see java.io.ObjectOutput
* @see java.io.ObjectInput
* @see java.io.Externalizable
* @since 1.1
*/
public interface Serializable {
}
没错 他是个空的!
所以我们需要先搞清楚什么是序列化?
序列化的含义就是:序列化 (Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程。
emmmm
说白了就是保存到硬盘或者其他地方进行存储一下!
那我们不妨做个小东西实验一样!爷天生傲骨,就不实现又能怎么样?
先上代码!
public class Person {
// private static final long serialVersionUID = 291613027204248679L;
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
private static void ObjectWriter() throws IOException {
FileOutputStream fos=new FileOutputStream("D:\\IO\\Person.object");
// 对象储存文件的规范
ObjectOutputStream oos=new ObjectOutputStream(fos);
oos.writeObject(new Person("Alien",21));
oos.close();
}
当我们点击运行!他报错了!没实现Serializable !
错误信息如下
Exception in thread "main" java.io.NotSerializableException: it.test.domain.Person
at java.base/java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1185)
at java.base/java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:349)
at it.test.domain.ObjectOutputStream_Test1.ObjectWriter(ObjectOutputStream_Test1.java:16)
at it.test.domain.ObjectOutputStream_Test1.main(ObjectOutputStream_Test1.java:7)
这个时候!我们就可以顺腾摸瓜(查看报错信息)!找到到底是哪里导致程序出现的异常!
然后我们在ObjectOutputStream.java
文件中发现了以下代码
节选:
if (obj instanceof String) {
writeString((String) obj, unshared);
} else if (cl.isArray()) {
writeArray(obj, desc, unshared);
} else if (obj instanceof Enum) {
writeEnum((Enum<?>) obj, desc, unshared);
} else if (obj instanceof Serializable) {
writeOrdinaryObject(obj, desc, unshared);
} else {
// 如果 都不符合 就会准备报异常了!!
if (extendedDebugInfo) {
throw new NotSerializableException(
cl.getName() + "\n" + debugInfoStack.toString());
} else {
throw new NotSerializableException(cl.getName());
}
}
奥 ! 他会将传入的对象进行判断:是否是String
?是否是枚举?是否是数组?是否实现Serializable
!
所以 对于源码查看 我们知道了如果他实现了Serializable 那么才会被处理! 这就是一种标识 !
如果他以上几种情况 (string array...)都不是!那么就会报出异常了!
原来如此!
所以这个东西:就是一种标识 !
不会被序列化的可怕家族!
当然!我们的设计师不能想着所有东西被序列化,那对象中有一些参数不想被序列化!(不!你不想!)我们该怎么办呢?
他们就是 static
和 transient
!
static
很好理解!这东西不归对象管,当你将属性声明成 static时,它就投靠了类 。
你序列化ObjectStream
Object!!!
是对象 管我类的小弟(static)啥事?
所以被static修饰的就无法序列化了!
transient
这东西就是java赋予你的神秘力量!毕竟我们不能把所有东西都设置成static,我们需要有属于对象的 不被序列化!
那么transient
就登场啦 如果你不想让他即属于对象又不会被序列化 那么你就给属性添加该关键字!
private transient int age;
这个时候 就不会被序列化了 当然每次反序列化都是默认值了!
但是理解归理解!这东西在java里面代码逻辑中到底是怎么实现的呢?
我们找到了ObjectStreamClass
中有如下代码:
这个方法 上面注释 我给大家翻译下!
返回与给定类声明的所有非静态非瞬态字段相对应的ObjectStreamFields
数组。
每个ObjectStreamField
都包含一个其代表的字段的Field对象。
如果没有默认的可序列化字段,则返回NO_FIELDS
private static ObjectStreamField[] getDefaultSerialFields(Class<?> cl) {
// 获取到序列化对象的参数数组
Field[] clFields = cl.getDeclaredFields();
ArrayList<ObjectStreamField> list = new ArrayList<>();
int mask = Modifier.STATIC | Modifier.TRANSIENT;
for (int i = 0; i < clFields.length; i++) {
//判断是不是 非静态非瞬态字段
// 添加所有 可序列化字段 进入ArrayList<ObjectStreamField> 然后进行后续操作
if ((clFields[i].getModifiers() & mask) == 0) {
list.add(new ObjectStreamField(clFields[i], false, true));
}
}
int size = list.size();
return (size == 0) ? NO_FIELDS :
list.toArray(new ObjectStreamField[size]);
}
没错 就是在这里判断的!
当然!Java序列化的本质就是将Java对象转化成字节数组来便于存储和传输的
这就是Java序列化一步非常重要的过程啦!
这里是🚽Java 每周不定时更新!喜欢的小伙伴可以点赞关注收藏哦!我们下个文章见!
网友评论