- transient 关键字:
当一个对象实现了 Serilizable 接口,这个对象就可以被序列化,我们不关心其内在的原理,只需要了解这个类实现了 Serilizable 接口,这个类的所有属性和方法都会自动序列化。而在开发过程中,我们可能要求:当对象被序列化时(写入字节序列到目标文件)时,有些属性需要序列化,而其他属性不需要被序列化,打个比方,如果一个用户有一些敏感信息(如密码,银行卡号等),为了安全起见,不希望在网络操作(主要涉及到序列化操作,本地序列化缓存也适用)中被传输,这些信息对应的变量就可以加上 transient 关键字。换句话说,这个字段的生命周期仅存于调用者的内存中而不会写到磁盘里持久化。
transient 的用途在于:阻止实例中那些用此关键字声明的变量持久化;当对象被反序列化时(从源文件读取字节序列进行重构),这样的实例变量值不会被持久化和恢复。例如,当反序列化对象——数据流(例如,文件)可能不存在时,原因是你的对象中存在类型为 java.io.InputStream 的变量,序列化时这些变量引用的输入流无法被打开。
使用小结:
①,一旦变量被 transient 修饰,变量将不再是对象持久化的一部分,该变量内容在序列化后无法获得访问。
②, transient 关键字只能修饰变量,而不能修饰方法和类。注意,本地变量是不能被transient关键字修饰的。变量如果是用户自定义类变量,则该类需要实现 Serializable 接口。
③,被 transient 关键字修饰的变量不再能被序列化,一个静态变量不管是否被 transient 修饰,均不能被序列化。
对于第三点,加上 static 之后,依然能把姓名输出。这是因为:反序列化后类中 static 型变量 name 的值为当前 JVM 中对应 static 变量的值,这个值是 JVM 中的不是反序列化得出的。
- volatile 关键字
volatile 修饰符告诉编译器被 volatile 修饰的变量可以被程序的其他部分改变。在多线程程序中,有时两个或更多的线程共享一个相同的实例变量。考虑效率问题,每个线程可以自己保存该共享变量的私有拷贝。实际的变量副本在不同的时候更新,如当进入 synchronized 方法时。
介绍:因为异步线程可以访问字段,所以有些优化操作是一定不能作用在字段上的。 volatile 有时
可以代替 synchronized 。但是volatile没办法保证对变量的操作的原子性。 volatile能在一定程度上保证有序性
**** volatile 关键字的两层语义***
一旦一个共享变量(类的成员变量、类的静态成员变量)被 volatile 修饰之后,那么就具备了两层语义:
1)内存可见性:保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的-即最新的值。
2)禁止进行指令重排序(为了减少内存操作速度远慢于CPU运行速度所带来的CPU空置影响,虚拟机会按照自己的一些规则将程序编写顺序打乱)。
使用 volatile 关键字的场景:
synchronized 关键字是防止多个线程同时执行一段代码,那么就会很影响程序执行效率,而 volatile 关键字在某些情况下性能要优于 synchronized ,但是要注意 volatile 关键字是无法替代 synchronized 关键字的,因为 volatile 关键字无法保证操作的原子性。
使用场景:
通过关键字 sychronize 可以防止多个线程进入同一段代码,在某些特定场景中, volatile 相当于一个轻量级的 sychronize ,因为不会引起线程的上下文切换,但是使用 volatile 必须满足两个条件:
① 对变量的写操作不依赖当前值,如多线程下执行 i++ ,是无法通过 volatile 保证结果准确性的。
② 该变量没有包含在具有其他变量的不变式中
实际上,这些条件表明,可以被写入 volatile 变量的这些有效值独立于任何程序的状态,包括变量的当前状态
- stricfp 关键字
用 strictfp 修饰类或方法,可以确保浮点运算(以及所有切断)正如早期的 Java 版本那样准确。切断只影响某些操作的指数。当一个类被 strictfp 修饰,所有的方法自动被 strictfp 修饰。
strictfp 的意思是 FP-strict ,也就是说精确浮点的意思。在 Java 虚拟机进行浮点运算时,如果没有指定 strictfp 关键字时, Java 的编译器以及运行环境在对浮点运算的表达式是采取一种近似于我行我素的行为来完成这些操作,以致于得到的结果往往无法令你满意。而一旦使用了 strictfp 来声明一个类、接口或者方法时,那么所声明的范围内Java的编译器以及运行环境会完全依照浮点规范IEEE-754来执行。因此如果你想让你的浮点运算更加精确,而且不会因为不同的硬件平台所执行的结果不一致的话,那就请用关键字 strictfp 。
介绍:字段不是对象持久状态的一部分,不应该把字段和对象一起串起。
你可以将一个类、接口以及方法声明为 strictfp ,但是不允许对接口中的方法以及构造函数声明 strictfp 关键字。