美文网首页马桶Java
马桶Java:1.Serializable 实现它做什么?

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

作者: 第二套广播体操 | 来源:发表于2020-03-24 12:28 被阅读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 每周不定时更新!喜欢的小伙伴可以点赞关注收藏哦!我们下个文章见!

    相关文章

      网友评论

        本文标题:马桶Java:1.Serializable 实现它做什么?

        本文链接:https://www.haomeiwen.com/subject/goloyhtx.html