`

Java关键字——transient

阅读更多
眼看就要2012了,这一年给自己树立的研究课题基本上因为工作的转型,最终都没能实现。开发经验开始消减,更没能赶上新技术。终于,我要恢复开发经验! 找回曾经的我!

最近被问到很多Java基础性的问题,突然发现自己长时间沉迷于框架整合的乐趣中,有关于底层这方面原来不曾深度研究,有必要恶补下了。
“transient”——“瞬态”,先不说这个翻译是否恰当,这个变量关键字一直不曾使用,简单的说就是被瞬态定义的变量不可序列号。或者这么给他换个名字——“不可序列化状态”?
打个比方,如果一个用户有一些敏感信息(譬如密码,银行卡号等),为了安全起见,不希望在网络操作(主要涉及到序列化操作,本地序列化缓存也适用)中被传输。这些信息对应的变量就可以被定义为transient类型。换句话说,这个字段的生命周期仅存于调用者的内存中。
定义People
public class People implements Serializable {
	private static final long serialVersionUID = 8294180014912103005L;

	/**
	 * 用户名
	 */
	private String username;
	/**
	 * 密码
	 */
	private transient String password;
}


密码字段为transient,这时候如果对该对象进行序列化,这个密码字段是不会被保存的。
为了代码简洁,未将流操作至于try-catch中,仅为演示,勿仿!
public static void main(String[] args) throws Exception {

		People p = new People();
		p.setUsername("snowolf");
		p.setPassword("123456");

		System.err.println("------操作前------");
		System.err.println("username: " + p.getUsername());
		System.err.println("password: " + p.getPassword());

		ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(
				"people.txt"));
		oos.writeObject(p);
		oos.flush();
		oos.close();

		ObjectInputStream ois = new ObjectInputStream(new FileInputStream(
				"people.txt"));
		p = (People) ois.readObject();

		ois.close();

		System.err.println("------操作后------");
		System.err.println("username: " + p.getUsername());
		System.err.println("password: " + p.getPassword());

	}

执行操作:
引用
------操作前------
username: snowolf
password: 123456
------操作后------
username: snowolf
password: null

密码字段为null,反序列化时根本没有从文件中获取到信息。
这个变量类型,理解起来都不费事,但就是适用场景,我一直纠结。
暂时整理如下,欢迎拍砖补充!
适用场景:
1.不打算序列化某字段的值,节省空间
2.传递序列化流的时候,不传递该值等


如上信息似乎跟JNI有关,欢迎拍砖!

11
7
分享到:
评论
10 楼 ifox 2013-07-23  
phrmgb 写道
学习了,这些东东有时感觉很偏的,但是特殊的业务用到这些知识

我看java许多源码都用到了呐。
9 楼 wushipan_easy 2011-12-30  
收藏一下,以后慢慢看
8 楼 PV_love 2011-12-30  
楼主写了
“为了代码简洁,未将流操作至于try-catch中,仅为演示,勿仿!”我没看到。
“比如说用transient定义一个int变量,用做计数,序列化/反序列化后必须重新核算。”
int变量不想写入流中,又得保证序列化前后一致,那之后就得再算一遍int变量的值,要不然有什么好办法么?

7 楼 snowolf 2011-12-30  
PV_love 写道
1.楼主的代码中,有关文件的操作应该放入try catch 中..
2.transient标识变量的作用是序列化的时候跳过该变量,主要应用的场景应该对象型的变量。
例如

class Hair{
private hairLength;
public Hair(int length){hairLength=length}
}

class body implements Serializable{
private Hair hair;
....
}

hair是body的成员变量,要保存body的时候需要保存hair,这就需要hair是序列化的,但是由于某些原因hair不是序列化的,那么就需要将hair标识成transient,序列化的时候跳过hair,但是可以将表示hair的状态,例如本例中的hairLength保存在流之中,然后在反序列化的时候,将hair变量通过hairLength重新生成,虽然没有保存hair本身,但是保存了表示hair的变量hairLength

我还没试过楼主的那种用法,用transient标识string型的变量,不知道这样可以可以。
如果可以,像这样的保存密码,反序列化的时候如何获得原来的密码呢?
安全方面的知识我不是很了解,我猜可能是将密码md5加密之后在再进行序列化,虽然理论上任何密码都是可以被破解的,但是网络上传输的密码都是这种方式吧?


为了代码简洁,我抛开了try-catch.
网络密文交互要比这个复杂,有安全强度要求。如想了解可以参考我的加密解密系列帖子。
别我用一个password字段,把大家引导沟里去了。
比如说用transient定义一个int变量,用做计数,序列化/反序列化后必须重新核算。这个意义就比较明显。对于这个瞬时变量不需要存储,只需要在内存中重新核算。期待继续拍砖!!拍出个金豆子!
6 楼 PV_love 2011-12-30  
1.楼主的代码中,有关文件的操作应该放入try catch 中..
2.transient标识变量的作用是序列化的时候跳过该变量,主要应用的场景应该对象型的变量。
例如

class Hair{
private hairLength;
public Hair(int length){hairLength=length}
}

class body implements Serializable{
private Hair hair;
....
}

hair是body的成员变量,要保存body的时候需要保存hair,这就需要hair是序列化的,但是由于某些原因hair不是序列化的,那么就需要将hair标识成transient,序列化的时候跳过hair,但是可以将表示hair的状态,例如本例中的hairLength保存在流之中,然后在反序列化的时候,将hair变量通过hairLength重新生成,虽然没有保存hair本身,但是保存了表示hair的变量hairLength

我还没试过楼主的那种用法,用transient标识string型的变量,不知道这样可以可以。
如果可以,像这样的保存密码,反序列化的时候如何获得原来的密码呢?
安全方面的知识我不是很了解,我猜可能是将密码md5加密之后在再进行序列化,虽然理论上任何密码都是可以被破解的,但是网络上传输的密码都是这种方式吧?

5 楼 沙舟狼客 2011-12-30  
transient,这个关键字用的不多
4 楼 phrmgb 2011-12-29  
学习了,这些东东有时感觉很偏的,但是特殊的业务用到这些知识
3 楼 snowolf 2011-12-29  
snowolf 写道
jyjava 写道
lz,你顺便讲讲volatile呀

这个“挥发态”跟序列化没关系,跟线程安全有关。我需要研究下如何模拟测试。。。

据说它比synchronized效率更高!
2 楼 snowolf 2011-12-29  
jyjava 写道
lz,你顺便讲讲volatile呀

这个“挥发态”跟序列化没关系,跟线程安全有关。我需要研究下如何模拟测试。。。
1 楼 jyjava 2011-12-29  
lz,你顺便讲讲volatile呀

相关推荐

Global site tag (gtag.js) - Google Analytics