论String字符串的可改变性

      相信任何学习java的人,都会在书中看到“String字符串是不可变的,一旦创建就不能修改”这样的经典语句。也就是说写出String s = “aaa”; 之后再写 s = "bbb"; 还是没用,jvm会在内存中重新创建一个String对象“bbb”,而原来的“aaa”对象依然存在。 而且内存中“aaa”这个内容是不能修改的.这就是大多数人所接触的String以及对String 的解。

      不过经过我最近的研究,发现利用反射还是可以修改String对象。

      首先,研究String类源码,String类有一个 char 数组value,是final的,用来当作存储字符串的容器,也就是说String s=“aaa”;这个字符串真正是这么存储的: value[0]='a';  value[1]='a';  value[2]='a'; 而且value是final的,这就是说value在编译时就已经决定了。因此,这就是我们所说的String是不可变的。

      不过,当这一切的一切遇上java无敌的反射机制时,就好象防备森严的公主闺房下竟然有一条直通大街的地道,任何通过这条地道的人都可以一窥公主闺房。所以,通过Java的反射就可以改变String对象的内容。

      那么为什么反射就能改变String的内容呢?这是因为final是只对编译有效的,对运行无效。也就是说可以在运行是改变final的内容(当然前提是不能照着常规思路写,那样都不可能通过编译,怎么能运行呢?),所以你可以在运行时通过反射得到String的value的值,然后将新的值设置到value中,就改变了String对象。具体代码如下:

String s = "aaaa";
		System.out.println(s);
		try{
			Field field = s.getClass().getDeclaredField("value"); //String 类含有一个名为value的char数组,用于存储
			field.setAccessible(true);
			if(null != field.get("value")){
            	System.out.println(field.get("value"));
            }else{
            	System.out.println("no data");
            }
			field.set(s, new char[] {'b','b','b','b'});
			System.out.println(s);
		}catch(NoSuchFieldException e){
			e.printStackTrace();
		}catch(SecurityException e){
			e.printStackTrace();
		}catch(IllegalAccessException e){
			e.printStackTrace();
		}

 

 运行结果如下:

aaaa
[C@1d057da
bbbb

不过,通过反射还有有一些问题的:例如,如下的代码替代String s = "aaaa";
就会抛出异常:

	String s = "aa";

 

只是简简单单的一句替代,运行结果就会改变,结果如下:

aa
[C@1d057da
bb
看到了吗?即使是下面new了一个大小为4的char数组,仍然只有两个‘b’存入到了s的value中。

这个好歹还没有抛出异常,要是替换成如下代码,更好的事情就来了,

String s = "aaaaaaa";

 抛出异常如下:

aaaaaaa
[C@1d057da
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException
	at java.lang.System.arraycopy(Native Method)
	at java.lang.String.getChars(Unknown Source)
	at java.io.BufferedWriter.write(Unknown Source)
	at java.io.Writer.write(Unknown Source)
	at java.io.PrintStream.write(Unknown Source)
	at java.io.PrintStream.print(Unknown Source)
	at java.io.PrintStream.println(Unknown Source)
	at Test.main(Test.java:21)

 呵呵,爽了吧。

由此可见,通过地道进入公主闺房毕竟不是见得阳光的事情,稍微有一点点不符合要求的都会被发现,只有当第一个char数组和第二个char数组的大小严格相等的时候才会出现我们期望的结果。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值