Java高阶语法---transient

背景:听说transient Java高阶语法是挺进BAT必经之路。

transient

Java中transient 关键字的作用,简单的说就是让某些被修饰的成员属性变量不被序列化。

这又扯到了序列化和反序列化:

Java中对象的序列化是指将对象转换成以字节序列的形式来表示,这些字节序列包含了对象的数据和信息,一个序列化后的对象可以被写到数据库或文件中,也可以用网络传输;就比如我们使用缓存cache/redis或远程调用RPC(网络传输)如一些密码等不想让人看到的敏感信息的时候,都要让缓存或传输的实体类实现Serializable接口,就是为了序列化实体类。 反序列化:序列化后的终极目的还是反序列化,恢复原先的Java对象,So序列化后的总结序列都是可以恢复为java对象的,此恢复过程就称为反序列化。

具体来说:

1、transient修饰的变量将不再是对象持久化的一部分,此变量内容在序列化后无法获得;

2、transient关键字只能修饰变量,本地变量除外,而不能修饰方法和类;

3、transient修饰的变量不能再被序列化,除此之外静态变量有无transient修饰都不能被序列化;

如下情况可以考虑使用transient关键字修饰:

1、类中的某个字段可以根据其他的字段推导出来,如一个盈利类有四个属性(出售单价、进价、利润),那么在序列化的时候,利润这个属性就没必要序列化了;

2、除此之外,具体看项目的业务需求,哪些字段不想被序列化则用transient 修饰即可;

另外:不序列化还有一个好处,那就是节省内存空间。

写个例子验证下:一个实体类读写流的操作,password用transient修饰,age用static修饰,userName常规操作,序列化实体类执行发现,password无法序列化,age结果值和反序列化之前不一致。

FYI:
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class TestTransient {
    public static void main(String[] args) throws Exception {
        TestTransient.transientTest("tjt", "password666", 22);
    }
    public static void transientTest(String userName, String password,Integer age) throws Exception {
        Account account = new Account();
        account.setUserName(userName);
        account.setPassword(password);
        account.setAge(age);
        log.info("before serializeble result is:"+account.getUserName()+"-"+account.getPassword()+"-"+account.getAge());
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
        objectOutputStream.writeObject(account);
        byte[] bytes = byteArrayOutputStream.toByteArray(); // 将account 转为流
        account.age = 18;   // 在反序列化之前改变age值,结果:反序列化后的结果没有从序列化中取age值
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
        ObjectInputStream objectInputStream = null;
        objectInputStream = new ObjectInputStream(byteArrayInputStream);
        Account accountAfter = (Account) objectInputStream.readObject();  // 从流中获取account
        log.info("after serializeble result is:"+accountAfter.getUserName()+"-"+accountAfter.getPassword()+"-"+accountAfter.getAge());
    }
    @Data
    static class  Account implements Serializable {
        private static final long serialVersionUID = -8994113761711738784L;
        private String userName;
        private transient String password;
        private static Integer age;
        public static Integer getAge() {
            return age;
        }
        public static void setAge(Integer age) {
            Account.age = age;
        }
    }
}
执行结果:

- before serializeble result is:tjt-password666-22
- after serializeble result is:tjt-null-18

原文地址:https://www.cnblogs.com/taojietaoge/p/10260145.html

时间: 2024-10-12 13:14:13

Java高阶语法---transient的相关文章

Java高阶语法---static

背景:听说static Java高阶语法是挺进BAT必经之路. static: 静态static,很多时候会令我望文生义,但是get到了static最重要的一点,其他的理解都还ok. static最重要的一点就是:类属性中被static所引用的变量会被当作Gabage Collection的root根节点,而root就意味着着这一类变量基本上是不会被GC回收的, 即使System.gc() 都不会被回收,So,static很容易引起内存泄漏. 官方的解释就是:static可以修饰属性.方法和内部

Java高阶语法---Volatile

背景:听说Volatile Java高阶语法亦是挺进BAT的必经之路. Volatile: volatile同步机制又涉及Java内存模型中的可见性.原子性和有序性,恶补基础一波. 可见性: 可见性简单的说是线程之间的可见性,一个线程修改的状态对另一个线程是可见对,也就是一个线程的修改结果另一个线程可以马上看到:但通常,我们无法确保执行读操作的线程能够时时的看到其他线程写入的值,So为了确保多个线程之间对内存写入操作可见性,必须使用同步机制:如用volatile修饰的变量就具有可见性,volat

Markdown 高阶语法

记录一些 Markdown 的高阶语法,想起来什么,再更新 分割线 两条分割线 *** *** 插入表格 Column Column Column Row Content Content | Column | Column | Column | |--|--|--| | Row | Content | Content | 行内代码 CTRL + ALL `CTRL + ALL` 反转符号 `CTRL + ALL` \`CTRL + ALL` 增加空行 <br> 删除线 00000000 ~~0

函数——基本语法,嵌套、匿名、高阶、递归函数

定义 函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可 特性 减小重复代码 使程序变的可扩展 易维护 函数参数 定义函数可以带参数,也可不带参数 形参:只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元.因此,形参只在函数内部有效.函数调用结束返回主调用函数则不能再使用该形参变量 实参:可以是常量.变量.表达式.函数等,无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参.因此应预先用赋值,输入等办

Java语言基本语法

Java语言基本语法 一.标识符和关键字 标识符 在java语言中,用来标志类名.对象名.变量名.方法名.类型名.数组名.包名的有效字符序列,称为“标识符”: 标识符由字母.数字.下划线.美元符号组成,且第一个字符不能是数字: java语言区分大小写: 标志符命名规则:类名首字母大写,变量名和方法名采用驼峰标志法,常量全大写,多个单词之间用“_”隔开,包名全小写: 关键字 在java语言中,有一些专门的词汇已经被赋予了特殊的含义,不能再使用这些词汇来命名标识符,这些专有词汇,称为“关键字”: j

聊聊React高阶组件(Higher-Order Components)

使用 react已经有不短的时间了,最近看到关于 react高阶组件的一篇文章,看了之后顿时眼前一亮,对于我这种还在新手村晃荡.一切朝着打怪升级看齐的小喽啰来说,像这种难度不是太高同时门槛也不是那么低的东西如今可不多见了啊,是个不可多得的 zhuangbility的利器,自然不可轻易错过,遂深入了解了一番. 概述 高阶组件的定义 React 官网上对高阶组件的定义: 高阶部件是一种用于复用组件逻辑的高级技术,它并不是 React API的一部分,而是从React 演化而来的一种模式. 具体地说,

第23讲: Scala高阶函数实战详解

高阶函数主要有两种: 一.将一个函数当做另外一个函数的参数(即函数参数) 普通函数的定义语法如下: def funName(para1:Type1,para2:Type2):Type = { do some things } 我们想象一下,如果将函数作为参数,那么函数的类型该怎么写呢? 函数的类型,其实就是输入输出的类型. 假设,我们需要将函数ceil作为参数,而ceil的定义如下   def ceil(x: Double): Double  = java.lang.Math.ceil(x) 那

【转】Scala学习——高阶函数

原文链接 http://nerd-is.in/2013-09/scala-learning-higher-order-functions/ 原文发表于:http://nerd-is.in/2013-09/scala-learning-higher-order-functions/ 在函数式编程语言中,函数是“头等公民”,可以像任何其他数据类型一样被传递和操作. 因为Scala混合了面向对象和函数式的特性,所以对Scala来说,函数是“头等公民”. 作为值的函数 1 2 3 import scal

JavaScript 高阶函数 + generator生成器

map/reduce map()方法定义在JavaScript的Array中,我们调用Array的map()方法,传入我们自己的函数,就得到了一个新的Array作为结果: function pow(x) { return x * x; } var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]; arr.map(pow); // [1, 4, 9, 16, 25, 36, 49, 64, 81] map()传入的参数是pow,即函数对象本身. 你可能会想,不需要map(),写