Java transient关键字使用小记

来源:互联网 发布:哔哩哔哩软件下载 编辑:程序博客网 时间:2024/06/02 19:42

转自;http://www.aichengxu.com/view/36695



1. transient的作用及使用方法 


我们都知道一个对象只要实现了Serilizable接口,这个对象就可以被序列化,java的这种序列化模式为开发者提供了很多便利,我们可以不必关系具体序列化的过程,只要这个类实现了Serilizable接口,这个类的所有属性和方法都会自动序列化。



然而在实际开发过程中,我们常常会遇到这样的问题,这个类的有些属性需要序列化,而其他属性不需要被序列化,打个比方,如果一个用户有一些敏感信息(如密码,银行卡号等),为了安全起见,不希望在网络操作(主要涉及到序列化操作,本地序列化缓存也适用)中被传输,这些信息对应的变量就可以加上transient关键字。换句话说,这个字段的生命周期仅存于调用者的内存中而不会写到磁盘里持久化。



总之,java 的transient关键字为我们提供了便利,你只需要实现Serilizable接口,将不需要序列化的属性前添加关键字transient,序列化对象的时候,这个属性就不会序列化到指定的目的地中。






  1. importjava.io.FileInputStream;

  2. importjava.io.FileNotFoundException;

  3. importjava.io.FileOutputStream;

  4. importjava.io.IOException;

  5. importjava.io.ObjectInputStream;

  6. importjava.io.ObjectOutputStream;

  7. importjava.io.Serializable;


  8. /**

  9. *@description使用transient关键字不序列化某个变量

  10. *注意读取的时候,读取数据的顺序一定要和存放数据的顺序保持一致

  11. *

  12. *@authorAlexia

  13. *@date2013-10-15

  14. */

  15. publicclassTransientTest{


  16. publicstaticvoidmain(String[]args){


  17. Useruser=newUser();

  18. user.setUsername("Alexia");

  19. user.setPasswd("123456");


  20. System.out.println("readbeforeSerializable:");

  21. System.out.println("username:"+user.getUsername());

  22. System.err.println("password:"+user.getPasswd());


  23. try{

  24. ObjectOutputStreamos=newObjectOutputStream(

  25. newFileOutputStream("C:/user.txt"));

  26. os.writeObject(user);//将User对象写进文件

  27. os.flush();

  28. os.close();

  29. }catch(FileNotFoundExceptione){

  30. e.printStackTrace();

  31. }catch(IOExceptione){

  32. e.printStackTrace();

  33. }

  34. try{

  35. ObjectInputStreamis=newObjectInputStream(newFileInputStream(

  36. "C:/user.txt"));

  37. user=(User)is.readObject();//从流中读取User的数据

  38. is.close();


  39. System.out.println("\nreadafterSerializable:");

  40. System.out.println("username:"+user.getUsername());

  41. System.err.println("password:"+user.getPasswd());


  42. }catch(FileNotFoundExceptione){

  43. e.printStackTrace();

  44. }catch(IOExceptione){

  45. e.printStackTrace();

  46. }catch(ClassNotFoundExceptione){

  47. e.printStackTrace();

  48. }

  49. }

  50. }


  51. classUserimplementsSerializable{

  52. privatestaticfinallongserialVersionUID=8294180014912103005L;


  53. privateStringusername;

  54. privatetransientStringpasswd;


  55. publicStringgetUsername(){

  56. returnusername;

  57. }


  58. publicvoidsetUsername(Stringusername){

  59. this.username=username;

  60. }


  61. publicStringgetPasswd(){

  62. returnpasswd;

  63. }


  64. publicvoidsetPasswd(Stringpasswd){

  65. this.passwd=passwd;

  66. }


  67. }</span>



输出为:






[java]view 
plaincopy 






  1. <spanstyle="font-size:12px;">readbeforeSerializable:

  2. username:Alexia

  3. password:123456


  4. readafterSerializable:

  5. username:Alexia

  6. password:null</span> 



密码字段为null,说明反序列化时根本没有从文件中获取到信息。



2. transient使用小结 



1)一旦变量被transient修饰,变量将不再是对象持久化的一部分,该变量内容在序列化后无法获得访问。



2)transient关键字只能修饰变量,而不能修饰方法和类。注意,本地变量是不能被transient关键字修饰的。变量如果是用户自定义类变量,则该类需要实现Serializable接口。



3)被transient关键字修饰的变量不再能被序列化,一个静态变量不管是否被transient修饰,均不能被序列化。



第三点可能有些人很迷惑,因为发现在User类中的username字段前加上transient关键字后,程序运行结果依然不变,即static类型的username也读出来为“Alexia”了,这不与第三点说的矛盾吗?实际上是这样的:第三点确实没错(一个静态变量不管是否被transient修饰,均不能被序列化),反序列化后类中static型变量username的值为当前JVM中对应static变量的值,这个值是JVM中的不是反序列化得出的,不相信?好吧,下面我来证明:




  1. importjava.io.FileInputStream;

  2. importjava.io.FileNotFoundException;

  3. importjava.io.FileOutputStream;

  4. importjava.io.IOException;

  5. importjava.io.ObjectInputStream;

  6. importjava.io.ObjectOutputStream;

  7. importjava.io.Serializable;


  8. /**

  9. *@description使用transient关键字不序列化某个变量

  10. *注意读取的时候,读取数据的顺序一定要和存放数据的顺序保持一致

  11. *

  12. *@authorAlexia

  13. *@date2013-10-15

  14. */

  15. publicclassTransientTest{


  16. publicstaticvoidmain(String[]args){


  17. Useruser=newUser();

  18. user.setUsername("Alexia");

  19. user.setPasswd("123456");


  20. System.out.println("readbeforeSerializable:");

  21. System.out.println("username:"+user.getUsername());

  22. System.err.println("password:"+user.getPasswd());


  23. try{

  24. ObjectOutputStreamos=newObjectOutputStream(

  25. newFileOutputStream("C:/user.txt"));

  26. os.writeObject(user);//将User对象写进文件

  27. os.flush();

  28. os.close();

  29. }catch(FileNotFoundExceptione){

  30. e.printStackTrace();

  31. }catch(IOExceptione){

  32. e.printStackTrace();

  33. }

  34. try{

  35. //在反序列化之前改变username的值

  36. User.username="jmwang";


  37. ObjectInputStreamis=newObjectInputStream(newFileInputStream(

  38. "C:/user.txt"));

  39. user=(User)is.readObject();//从流中读取User的数据

  40. is.close();


  41. System.out.println("\nreadafterSerializable:");

  42. System.out.println("username:"+user.getUsername());

  43. System.err.println("password:"+user.getPasswd());


  44. }catch(FileNotFoundExceptione){

  45. e.printStackTrace();

  46. }catch(IOExceptione){

  47. e.printStackTrace();

  48. }catch(ClassNotFoundExceptione){

  49. e.printStackTrace();

  50. }

  51. }

  52. }


  53. classUserimplementsSerializable{

  54. privatestaticfinallongserialVersionUID=8294180014912103005L;


  55. publicstaticStringusername;

  56. privatetransientStringpasswd;


  57. publicStringgetUsername(){

  58. returnusername;

  59. }


  60. publicvoidsetUsername(Stringusername){

  61. this.username=username;

  62. }


  63. publicStringgetPasswd(){

  64. returnpasswd;

  65. }


  66. publicvoidsetPasswd(Stringpasswd){

  67. this.passwd=passwd;

  68. }


  69. }


运行结果为:







[java]view 
plaincopy 






  1. <spanstyle="font-size:12px;">readbeforeSerializable:

  2. username:Alexia

  3. password:123456


  4. readafterSerializable:

  5. username:jmwang

  6. password:null</span> 





这说明反序列化后类中static型变量username的值为当前JVM中对应static变量的值,为修改后jmwang,而不是序列化时的值Alexia。


3. transient使用细节——被transient关键字修饰的变量真的不能被序列化吗? 


思考下面的例子:




  1. importjava.io.Externalizable;

  2. importjava.io.File;

  3. importjava.io.FileInputStream;

  4. importjava.io.FileOutputStream;

  5. importjava.io.IOException;

  6. importjava.io.ObjectInput;

  7. importjava.io.ObjectInputStream;

  8. importjava.io.ObjectOutput;

  9. importjava.io.ObjectOutputStream;


  10. /**

  11. *@descripitonExternalizable接口的使用

  12. *

  13. *@authorAlexia

  14. *@date2013-10-15

  15. *

  16. */

  17. publicclassExternalizableTestimplementsExternalizable{


  18. privatetransientStringcontent="是的,我将会被序列化,不管我是否被transient关键字修饰";


  19. @Override

  20. publicvoidwriteExternal(ObjectOutputout)throwsIOException{

  21. out.writeObject(content);

  22. }


  23. @Override

  24. publicvoidreadExternal(ObjectInputin)throwsIOException,

  25. ClassNotFoundException{

  26. content=(String)in.readObject();

  27. }


  28. publicstaticvoidmain(String[]args)throwsException{


  29. ExternalizableTestet=newExternalizableTest();

  30. ObjectOutputout=newObjectOutputStream(newFileOutputStream(

  31. newFile("test")));

  32. out.writeObject(et);


  33. ObjectInputin=newObjectInputStream(newFileInputStream(newFile(

  34. "test")));

  35. et=(ExternalizableTest)in.readObject();

  36. System.out.println(et.content);


  37. out.close();

  38. in.close();

  39. }

  40. }


content变量会被序列化吗?好吧,我把答案都输出来了,是的,运行结果就是:



是的,我将会被序列化,不管我是否被transient关键字修饰



这是为什么呢,不是说类的变量被transient关键字修饰以后将不能序列化了吗?



我们知道在Java中,对象的序列化可以通过实现两种接口来实现,若实现的是Serializable接口,则所有的序列化将会自动进行,若实现的是Externalizable接口,则没有任何东西可以自动序列化,需要在writeExternal方法中进行手工指定所要序列化的变量,这与是否被transient修饰无关。因此第二个例子输出的是变量content初始化的内容,而不是null。









原文地址:http://blog.csdn.net/lanxuezaipiao/article/details/16358677


0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 商铺没有房产证不能办理消防怎么办 亳州办事大厅登录密码忘记了怎么办 户口已迁出结婚证丢了怎么办 户口已迁出多年结婚证丢了怎么办 芜湖长信正式工没转正怎么办辞职 买到9个月库存车怎么办 买到5个月库存车怎么办 把4s店新车撞了怎么办 网址导航已取消打不开网页是怎么办 如果邦华手机充电口有杂物怎么办? 当发生灾害或突发事故时怎么办 物流信息和和收货地址不一样怎么办 小孩手被电梯门夹了怎么办 车管所50选一没看中的号码怎么办 长沙芙蓉区电动车被交警扣了怎么办 驾照正在考的时候住址变了怎么办 身份证到期了驾驶证上的号码怎么办 小车占道跟大车刮交警怎么办 邻居把消防栓的位置占用了怎么办 查环保要停业整改一个月怎么办 抽油烟机管道公共排烟道漏烟怎么办 深圳龙华电动车被交警扣了怎么办 英国平邮寄到中国丢件怎么办 安卓app与设备不兼容怎么办 手机卡坏了收不到快递短信怎么办 pph手术后钛钉没有脱落怎么办 右侧附件囊状透明声可怎么办 刚刚出生小孩睾丸没有掉下来怎么办 汽车被依非法营运之由扣押怎么办 老婆结婚小孩两个又上夜场该怎么办 对于不断无理要求赔偿的房东怎么办 欠的钱越来越多不知道怎么办了 手机壳的开机按键不好按怎么办 对方把保权的房子卖给我怎么办 内存卡在手机上显示损坏怎么办 内存卡显示但是下载不了东西怎么办 相机sd卡没办法读卡怎么办 尼康相机新sd卡显示满了怎么办 修冰箱没几个月又坏了怎么办 星露谷物语活动中心成了仓库怎么办 你家如果油锅起火时应该怎么办