刚才在学习 HashMap 源码的过程中,发现了一个transient 关键字,发现自己不熟悉,然后也又开始了挖掘。
一.transient 的使用总结
1、transient关键字只能修饰变量,而不能修饰方法和类。注意,本地变量是不能被transient关键字修饰的。
2、被transient关键字修饰的变量不再能被序列化,一个静态变量不管是否被transient修饰,均不能被序列化。
3、一旦变量被transient修饰,变量将不再是对象持久化的一部分,该变量内容在序列化后无法获得访问。也可以认为在将持久化的对象反序列化后,被transient修饰的变量将按照普通类成员变量一样被初始化。
二.transient 有什么作用?
发现transient 可以让jvm不对某些变量进行序列化,使得在反序列的过程中获取不到改变量。(听着好像感觉没有用处,但实际应用确实还是会用到以及在面试时也会问到。)
实际用到的地方:譬如 InputStream 这个类没有实现Serializable接口的,但要对拥有InputStream 变量的类进行序列化的时候,便会出现java.io.NotSerializableException 。此时我们就需要使用 transient 修饰 InputStream 变量。
三.代码示例:
第一个类:
import java.io.Serializable; public class ClassLib implements Serializable { private transient InputStream is; private int majorVer; private int minorVer; private transient static Integer ainte; private transient static Integer astatint=3; ClassLib(InputStream is) throws IOException { System.out.println("ClassLib(InputStream) called"); this.is = is; DataInputStream dis; ainte=1; if (is instanceof DataInputStream) dis = (DataInputStream) is; else dis = new DataInputStream(is); if (dis.readInt() != 0xcafebabe) throw new IOException("not a .class file"); minorVer = dis.readShort(); majorVer = dis.readShort(); } int getMajorVer() { return majorVer; } int getMinorVer() { return minorVer; } void showIS() { System.out.println(is); } public Integer getAinte() { return ainte; } public void setAinte(Integer ainte) { this.ainte = ainte; } public static int getAstatint() { return astatint; } public static void setAstatint(int astatint) { ClassLib.astatint = astatint; } }第二个类:
import java.io.*; public class TransDemo { public static void main(String[] args) throws IOException { ClassLib cl = new ClassLib(new FileInputStream("C:\\Users\\Administrator\\Desktop\\HelloDate.class"));//此处参数指定为一个class文件 System.out.printf("Minor version number: %d%n", cl.getMinorVer()); System.out.printf("Major version number: %d%n", cl.getMajorVer()); System.out.printf("getAinte : %d%n", cl.getAinte()); System.out.printf("getAstatint : %d%n", cl.getAstatint()); cl.showIS(); try (FileOutputStream fos = new FileOutputStream("x.ser"); ObjectOutputStream oos = new ObjectOutputStream(fos)) { oos.writeObject(cl); } cl = null; try (FileInputStream fis = new FileInputStream("x.ser"); ObjectInputStream ois = new ObjectInputStream(fis)) { System.out.println(); cl = (ClassLib) ois.readObject(); System.out.printf("Minor version number: %d%n", cl.getMinorVer()); System.out.printf("Major version number: %d%n", cl.getMajorVer()); System.out.printf("getAinte : %d%n", cl.getAinte()); System.out.printf("getAstatint : %d%n", cl.getAstatint()); cl.showIS(); } catch (ClassNotFoundException cnfe) { System.err.println(cnfe.getMessage()); } } }
运行结果:
ClassLib(InputStream) called
Minor version number: 0
Major version number: 52
getAinte : 1
getAstatint : 3
java.io.FileInputStream@12a3a380
Minor version number: 0
Major version number: 52
getAinte : 1
getAstatint : 3
null
Minor 和 Major 在反序列化后都有数值是因为,其被正常序列化。
Ainte和Astatint是有由于静态变量的关系(静态变量一次初始化赋值,之后该类的对象的此变量均会有相同数值,与序列化无关)
Is不出现异常和现实Null数值,体现了transient不让其序列化的作用。
四.附加内容(关于静态变量的补充)
1.只在类第一次使用时加载时进行初始化 表明第一次用就要初始化,后面根据需要是可以再次赋值。(有需要就赋值)
2.公共性,就是说,一个类的静态成员,它是属于大伙的,所有的类对象共享的,不像成员变量是自己的。
代码示例:
第一个类:
public class TestStatic { private static Integer i; public TestStatic(Integer w) { this.i=w; } public TestStatic() { } public static Integer getI() { return i; } public static void setI(Integer i) { TestStatic.i = i; } }第二个类:
public class Test { public static void main(String[] args) { TestStatic te=new TestStatic(2); System.out.println(te.getI()); TestStatic te2=new TestStatic(); System.out.println(te.getI()); } }分析:发现第二个te2 对象有i数值的时候,大家一定能明白静态变量的含义了。
各位老铁,有错误一定要提出来哟,大家一起学习。