• transient关键字和@Transient 注解


    版权声明:本文为CSDN博主「wolfshadow.cn」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/u010188178/article/details/83581506

    百度百科的解释:

            Java语言的关键字,变量修饰符,如果用transient声明一个实例变量,当对象存储时,它的值不需要维持。换句话来说就是,用transient关键字标记的成员变量不参与序列化过程。

    作用:
            Java的serialization提供了一种持久化对象实例的机制。当持久化对象时,可能有一个特殊的对象数据成员,我们不想用serialization机制来保存它。为了在一个特定对象的一个域上关闭serialization,可以在这个域前加上关键字transient。当一个对象被序列化的时候,transient型变量的值不包括在序列化的表示中,然而非transient型的变量是被包括进去的。


     

    编码试验加以证明:

    1.自定义类(为了方便,我直接在main方法所在类中添加的一个静态属性类,或者叫成员类

    public static class TransientTest implements Serializable{
            private static final long serialVersionUID = 233858934995755239L;
            private String name1;
            private transient String name2;
            
            public TransientTest(String name1,String name2){
                this.name1 = name1;
                this.name2 = name2;
            }
            public String toString(){
                return String.format("TransientTest.toString(): name1=%s,name2=%s", name1,name2);
            }
        }

    2.写一个测试方法

    public static void testTransient(){
            String name1="常规属性",name2="transient修饰的属性";
            TransientTest test = new TransientTest(name1, name2);
            System.out.println("序列化前:"+test.toString());
            ObjectOutputStream outStream;
            ObjectInputStream inStream;
            String filePath = "D:/test/object/TransientTest.obj";
            try {
                outStream = new ObjectOutputStream(new FileOutputStream(filePath));
                outStream.writeObject(test);
                
                inStream = new ObjectInputStream(new FileInputStream(filePath));
                TransientTest readObject = (TransientTest)inStream.readObject();
                System.out.println("序列化后:"+readObject.toString());
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

    3.在main方法中执行,然后可以看到得到的结果为

    印证了上面所讲的“用transient关键字标记的成员变量不参与序列化过程”。

    用二进制查看器打开这个文件也可以看到,数据中只有name1,没有name2。(请忽略乱码问题,这个不是重点哈。)

    延伸:

    在查看JDK源码的时候会发现很多地方都会加上transient关键字来修饰一些属性,那究竟是出于什么考虑才这么做呢?

    我觉得,应该是为了节约磁盘空间,避免造成不必要的浪费吧。

    以ArrayList中的 transient Object[] elementData 为例,这个成员变量的注释为:

     

    翻译出来就是:

    / * *

    *存储ArrayList元素的数组缓冲区。

    * ArrayList的容量是这个数组缓冲区的长度。任何

    *带有elementData的空ArrayList == DEFAULTCAPACITY_EMPTY_ELEMENTDATA

    *当添加第一个元素时,将被扩展到DEFAULT_CAPACITY。

    * /

            这个缓冲区的容量实际上并不是ArrayList的容量,因为其实际上会预留一些空间,当空间不足时还会扩容,为减少浪费,因此在序列化时不会按照默认算法将这个成员变量写入磁盘。而是写了个writeObject方法,序列化时会调用这个方法将其持久化,在反序列化是,调用readObject,将其恢复出来。

    这2个方法为:

     

    参考ArrayList,在上面的TransientTest中添加2个方法,见代码:

    public static class TransientTest implements Serializable{
            private static final long serialVersionUID = 233858934995755239L;
            private String name1;
            private transient String name2;
            
            public TransientTest(String name1,String name2){
                this.name1 = name1;
                this.name2 = name2;
            }
            public String toString(){
                return String.format("TransientTest.toString(): name1=%s,name2=%s", name1,name2);
            }
     
            private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
                s.defaultWriteObject();
                s.writeObject(name2);
            }
            private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
                s.defaultReadObject();
                name2=String.valueOf(s.readObject());
            }
        }

    然后在main方法中执行testTransient(),此时得到的结果是:

     @Transient 注解

    实体类中使用了@Table注解后,想要添加表中不存在的字段,就要使用@Transient这个注解了。

    使用 @Transient 表示该属性并非是一个要映射到数据库表中的字段,只是起辅助作用.ORM框架将会忽略该属性

    注解可以加在属性上 也可以加在get()上面

  • 相关阅读:
    "字符反向拼接"组件:<reverse> —— 快应用组件库H-UI
    "首字母变大写"组件:<capitalize> —— 快应用组件库H-UI
    "字母全变大写"组件:<uppercase> —— 快应用组件库H-UI
    "字母全变小写"组件:<lowercase> —— 快应用组件库H-UI
    "多行文本"组件:<multi> —— 快应用组件库H-UI
    "斜体显示"组件:<i> —— 快应用组件库H-UI
    捕捉AVPlayerViewController 系统原生工具栏的出现、隐藏事件
    (简单实用)Android支付宝商家收款语音播报
    使用wkwebview时,push后,再pop返回,报错
    安卓进度条两边圆角+渐变的拓展
  • 原文地址:https://www.cnblogs.com/doyi111/p/11705063.html
Copyright © 2020-2023  润新知