马桶Java

马桶Java:1.Serializable 实现它做什么?

2020-03-24  本文已影响0人  第二套广播体操

马桶🚽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 {
}

没错 他是个空的

image.png
所以我们需要先搞清楚什么是序列化?
序列化的含义就是:序列化 (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...)都不是!那么就会报出异常了!
原来如此!
所以这个东西:就是一种标识 !

不会被序列化的可怕家族!

当然!我们的设计师不能想着所有东西被序列化,那对象中有一些参数不想被序列化!(不!你不想!)我们该怎么办呢?
他们就是 statictransient
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 每周不定时更新!喜欢的小伙伴可以点赞关注收藏哦!我们下个文章见!

上一篇 下一篇

猜你喜欢

热点阅读