谈到这个transient这个关键字,我们应该会立马想到序列化这个过程;什么是序列化?什么又是反序列化呢?序列化就是将对象转化内成二进制,而反序列化就是就二进制文件转换成对象的过程。一旦变量使用了transient之后,那么该变量是不会被序列化的。什么场景下使用这个关键字呢,比如说用户的密码这种敏感的字段来说,我们不希望通过网络去传输,而只需要让它存在于内存当中即可。不希望在网络操作(主要涉及到序列化操作,本地序列化缓存也适用)中被传输,这些信息对应的变量就可以加上transient关键字。换句话说,这个字段的生命周期仅存于调用者的内存中而不会写到磁盘里持久化。下面我们看一个Demo(这个例子没有使用transient关键字)。

package com.gosaint.server;

import java.io.Serializable;

/**
* @Authgor: gosaint
* @Description:
* @Date Created in 10:32 2018/3/9
* @Modified By:实现了序列化接口
*/
public class User implements Serializable{
private String username;
private String password;
private String agent; public String getUsername() {
return username;
} public void setUsername(final String username) {
this.username = username;
} public String getPassword() {
return password;
} public void setPassword(final String password) {
this.password = password;
} public String getAgent() {
return agent;
} public void setAgent(final String agent) {
this.agent = agent;
} @Override public String toString() {
return "User{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
", agent='" + agent + '\'' +
'}';
}
}

实现了Seriable接口,接着我们使用对象流写出和写入:

package com.gosaint.server;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream; /**
* @Authgor: gosaint
* @Description:
* @Date Created in 10:33 2018/3/9
* @Modified By:
*/
public class TransientTest {
public static void main(String[] args) {
User user=new User();
user.setUsername("caozg");
user.setPassword("123456");
user.setAgent("男"); System.out.println("序列化之前读取");
System.out.println("username :"+user.getUsername());
System.out.println("password :"+user.getPassword());
System.out.println("agent :"+user.getAgent()); //将对象写出到流
try {
ObjectOutputStream os=new ObjectOutputStream(new FileOutputStream("D:/user.txt"));
// 将对象写入文件
os.writeObject(user);
os.flush();
os.close();
}catch (FileNotFoundException e){
e.printStackTrace();
}catch (Exception e){
e.printStackTrace();
}
try {
ObjectInputStream ois=new ObjectInputStream(new FileInputStream("D:/user.txt"));
user=(User)ois.readObject();//读取对象
ois.close();
System.out.println("===================");
System.out.println("序列化之后的数据读取");
System.out.println("username :"+user.getUsername());
System.out.println("password :"+user.getPassword());
System.out.println("agent :"+user.getAgent()); }catch (FileNotFoundException e){
e.printStackTrace();
}catch (IOException e){
e.printStackTrace();
}catch (ClassNotFoundException e){
e.printStackTrace();
} }
}

看生成之后的user.txt序列化文件:

aced 0005 7372 0017 636f 6d2e 676f 7361
696e 742e 7365 7276 6572 2e55 7365 72ee
4b64 d20f b657 4a02 0003 4c00 0561 6765
6e74 7400 124c 6a61 7661 2f6c 616e 672f
5374 7269 6e67 3b4c 0008 7061 7373 776f
7264 7100 7e00 014c 0008 7573 6572 6e61
6d65 7100 7e00 0178 7074 0003 e794 b774
0006 3132 3334 3536 7400 0563 616f 7a67

看不懂吧,反正是二进制文件,我也看不懂!那么就看看控制台的输出吧。

序列化之前读取
username :caozg
password :123456
agent :男
===================
序列化之后的数据读取
username :caozg
password :123456
agent :男

此时发现对象完全被序列化操作了。接下来我们对密码使用transient关键字;

public class User  implements Serializable{
private String username;
private transient String password;
private String agent;
}

控制台的打印如下:

序列化之前读取
username :caozg
password :123456
agent :男
===================
序列化之后的数据读取
username :caozg
password :null
agent :男

密码没有被序列化;

关于transient关键字的使用总结:

  1>:一旦变量使用了transient关键字修饰,那么将不能被序列化;该变量的内容在对象序列化之后也无法访问

  2>:transient只能修饰成员变量,不能修饰类和方法,不可以修饰局部变量;如果变量是对象类型,则该对象也要实现Seriable接口

  3>:当变量使用static修饰,则该变量不可以被序列化;一个静态变量不管是否被transient修饰,均不能被序列化。因为变量被static修饰,它属于类变量,属于JVM所有。

请看下面的代码,变量username被static修饰了。

public class User  implements Serializable{
private static String username;
private transient String password;
private String agent;
}
序列化之前读取
username :caozg
password :123456
agent :男
===================
序列化之后的数据读取
username :caozg
password :null
agent :男

发现输入输出username相同,那么是不是被序列化了呢?其实不是哈。原因我在第三点已经说明。下面我在序列化之前修改代码:

package com.gosaint.server;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream; /**
* @Authgor: gosaint
* @Description:
* @Date Created in 10:33 2018/3/9
* @Modified By:
*/
public class TransientTest {
public static void main(String[] args) {
User user=new User();
user.setUsername("caozg");
user.setPassword("123456");
user.setAgent("男"); System.out.println("序列化之前读取");
System.out.println("username :"+user.getUsername());
System.out.println("password :"+user.getPassword());
System.out.println("agent :"+user.getAgent()); //将对象写出到流
try {
ObjectOutputStream os=new ObjectOutputStream(new FileOutputStream("D:/user.txt"));
// 将对象写入文件
os.writeObject(user);
os.flush();
os.close();
}catch (FileNotFoundException e){
e.printStackTrace();
}catch (Exception e){
e.printStackTrace();
}
try {
user.setUsername("caozg2222");
ObjectInputStream ois=new ObjectInputStream(new FileInputStream("D:/user.txt"));
user=(User)ois.readObject();//读取对象
ois.close();
System.out.println("===================");
System.out.println("序列化之后的数据读取");
System.out.println("username :"+user.getUsername());
System.out.println("password :"+user.getPassword());
System.out.println("agent :"+user.getAgent()); }catch (FileNotFoundException e){
e.printStackTrace();
}catch (IOException e){
e.printStackTrace();
}catch (ClassNotFoundException e){
e.printStackTrace();
} }
}
序列化之前读取
username :caozg
password :123456
agent :男
===================
序列化之后的数据读取
username :caozg2222
password :null
agent :男

看到了吗,本来序列化的是caozg。但是最后写出的是caozg2222。因此static修饰的变量不能被序列化。

看如下的代码:

package com.gosaint.server;

import java.io.Externalizable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream; /**
* @Authgor: gosaint
* @Description:
* @Date Created in 11:30 2018/3/9
* @Modified By:
*/
public class ExternalizableTest implements Externalizable {
private transient String content = "是的,我将会被序列化,不管我是否被transient关键字修饰";
@Override
public void writeExternal(final ObjectOutput objectOutput) throws IOException {
objectOutput.writeObject(content);
} @Override
public void readExternal(final ObjectInput objectInput) throws IOException, ClassNotFoundException {
content=(String) objectInput.readObject();
}
public static void main(String[] args) throws Exception { ExternalizableTest et = new ExternalizableTest();
System.out.println("序列化之前");
System.out.println(et.content);
ObjectOutput out = new ObjectOutputStream(new FileOutputStream(
new File("test")));
out.writeObject(et);
ObjectInput in = new ObjectInputStream(new FileInputStream(new File(
"test")));
et = (ExternalizableTest) in.readObject();
System.out.println("序列化之后");
System.out.println(et.content);
out.close();
in.close();
}
}

Externalizable 实例类的唯一特性是可以被写入序列化流中,该类负责保存和恢复实例内容。

打印内容如下:

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

  

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

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

transient关键字的理解的更多相关文章

  1. 【Java编程】volatile和transient关键字的理解

    理解volatile   volatile是java提供的一种轻量级的同步机制,所谓轻量级,是相对于synchronized(重量级锁,开销比较大)而言的.   根据java虚拟机的内存模型,我们知道 ...

  2. Java transient关键字的理解

    transient [ˈtrænziənt] adj. 短暂的; 转瞬即逝的; 临时的 n 临时旅客; 瞬变现象; 候鸟; 1. transient的作用及使用方法       我们都知道一个对象只要 ...

  3. Java中的Serializable接口transient关键字,及字节、字符、对象IO

    1.什么是序列化和反序列化Serialization是一种将对象转为为字节流的过程:deserialization是将字节流恢复为对象的过程. 2.什么情况下需要序列化a)当你想把的内存中的对象保存到 ...

  4. Java对象表示方式1:序列化、反序列化和transient关键字的作用

    平时我们在Java内存中的对象,是无法进行IO操作或者网络通信的,因为在进行IO操作或者网络通信的时候,人家根本不知道内存中的对象是个什么东西,因此必须将对象以某种方式表示出来,即存储对象中的状态.一 ...

  5. 序列化、反序列化和transient关键字的作用

    引言 将 Java 对象序列化为二进制文件的 Java 序列化技术是 Java 系列技术中一个较为重要的技术点,在大部分情况下,开发人员只需要了解被序列化的类需要实现 Serializable 接口, ...

  6. 干了这杯Java之transient关键字

    看源码的时候,发现transient这个关键字,不甚理解,查找资料发现:不被序列化 疑问: 静态变量是不是不被序列化? public class User implements Serializabl ...

  7. java中的transient关键字详解

    目录 1.何谓序列化? 2.为何要序列化? 3.序列化与transient的使用 4.java类中serialVersionUID作用 5.transient关键字小结 前言 说实话学了一段时间jav ...

  8. Java的transient关键字

    Java的transient关键字   Java 中的 transient 关键字被用来表示变量将不被序列化处理.那么在理解 transient 关键字之前,我们先了解下什么是序列化. 什么是序列化 ...

  9. transient关键字和serialVersionUID

    此文章很大部分转载于Java的架构师技术栈微信公众号,博主均测试通过加上自己理解写出 最近阅读java集合的源码,发现transient关键字,就了解了一下他的用法,transient关键字一般在实现 ...

随机推荐

  1. java:Writer/Reader字符流操作

    字符流的操作: 字节流的操作,是直接映射文件的:file->文件 字符流的操作是需要存在缓存区的:file->缓冲区->文件 (中文处理,一般用字符流) public static ...

  2. UML类图(二)----------类与类之间的关系之关联(聚合与组合)

    类与类之间的关系: 在软件系统中,类并不是孤立存在的,类与类之间存在各种关系,对于不同类型的关系,UML提供了不同的表示方式.       1. 关联关系 关联(Association)关系是类与类之 ...

  3. JavaScript作用域新总结

    作用域是什么 当我们将变量引入程序后,这些变量住在哪里,当程序需要的时候如何找到他们?这些问题都需要一个规则来存储变量,并且之后可以方便的找到这些变量,这套规则就被称为 作用域 .(管理变量的规则) ...

  4. Node的异步I/O

    node是单线程非阻塞异步I/O的模式. 阻塞I/O:完成整个数据获取的过程: 非阻塞I/O:不带数据,直接立即返回,要获取数据,还需通过文件描述符再次读取. node完成整个异步I/O的有事件循环. ...

  5. python--基本代码规范

    python代码规范:一.标识符 所谓的标识符就是对变量.常量.函数.类等对象起的名字 python语言在任何场景都严格区分大小写!!! python对于标识符的命名有如下规定: 第一个字符必须是字母 ...

  6. 31 python下实现并发编程

    一 背景知识 顾名思义,进程即正在执行的一个过程.进程是对正在运行程序的一个抽象. 进程的概念起源于操作系统,是操作系统最核心的概念,也是操作系统提供的最古老也是最重要的抽象概念之一.操作系统的其他所 ...

  7. Zijian-lv #3 树句节狗提

    如你所见,这是一道狗题 一棵树,多次询问与一个点距离至少为 $k$ 的点的权值和 $n,q \leq 2525010$ sol: 长链剖分 需要注意的是这道题卡空间 我把我所有的 vector 换成链 ...

  8. 【java规则引擎】简单规则的rete网络示意图

    一个Fact通过Session添加到规则网络中,如何进行规则匹配的大致过程如下 (1)通过根结点对象从EntryPointNode的Map集合中找到相应的EntryPointNode对象 (2)Ent ...

  9. shell实现文件内容查询如输入姓名结果显示电话号码等信息

    #!/bin/awk -f BEGIN{FS=","; if(ARGC>2){name=ARGV[1];delete ARGV[1]} else{ echo "pl ...

  10. redis设置为null问题

    查看源码后发现,redis没有删除方法,本想给他设置为null,但是redis报错,所有仔细想了一下,发现redis提供了一个时间限制方法,所有可以让redis的时间限制为1s,就想当于删除redis ...