本帖最后由 大蓝鲸Java 于 2017-3-16 16:33 编辑
【南京校区】毁人不倦篇之一 --- String真的是不变的吗?
在我们平时Java的学习过程中,有一些常识性问题,我们都默守陈规的遵守了这些的原则,殊不知我们的Java是一个极具自由的语言,正如我们程序员的一样,放荡不羁爱自由。 在我们平时写一些代码的时候,如果多思考一下,往往会有一些出乎意料的答案产生。
比如:毁人不倦篇之一 --- String真的是不变的吗?
在我们平时的学习过程中有一个知识点,String和StringBuffer的区别。我们往往会认为StringBuffer是String的一个缓冲区。StringBuffer是可变的,而String是不可变的。
但是我们确可以通过一些非正常手段来让String进行改变。
首先,解释一下为什么平时我们会认为String是不可变的。在String的源码中String其实是以一个private final char value[];这样的数组将每一个字符存到一个名为value的数组中的。为final修饰,所以是这个数组的地址值不能发生改变。且此数组被private修饰,而String内部没有提供对这个数组修改的一些方法或者操作,所以我们不能在外界对这个数组进行修改。众所周知,如果我们得到一个数组的对象,是可以对这个数组的内部元素进行修改的。所以我们可以通过这个原理,让我们的String进行修改,打破常规!
怎么样能获取到String类中的private 修饰的那个对象呢?这个就成为了关键。
在Java中提供了一个技术叫做反射,在反射面前一切都是赤裸裸的。
代码如下:
String s = "abcd";//创建一个字符串对象
Class clazz = s.getClass();//通过反射获取到String的字节码文件
Field field = clazz.getDeclaredField("value");//得到私有的成员变量value
field.setAccessible(true);//将私有权限消除
char[] value = (char[]) field.get(s);//得到value数组的对象
value[2] = 'Q';//将其中任意一个索引上的值变成另一个值
System.out.println(s);//最终将字符串打印
此时我们发现通过反射技术,可以实现字符串的改变!
|