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();},美国空间酒般的思念,一饮就醉,醉时就用全部的热情读这忧伤的月色,

String的可改变性

相关文章:

你感兴趣的文章:

标签云: