都说String是不可变的,但是究竟哪里不可变,是内容不可变还是什么不可变,又是怎么个变法,对此真的头大!为此我苦思不得其解,终于让我找到梗了!
首先我看了String源码,String被final修饰,而String类内的方法也都是被final修饰的。众所周知String底层是char数组,这个数组继而也是被final修饰。
一旦被final修饰,其初始化后内容是不可变的。数组被final修饰,数组长度是不可变的。
在IDE编辑器,Ctrl+N找到String类源码,再Ctrl+Alt+O,会出现以下信息,提示String是只读的,不能被修改。(这里的快捷键以自己配置的快捷键为主)
![521f592f1ec5b91bf8ef6d6eabf912c4.png](https://i-blog.csdnimg.cn/blog_migrate/c03e15d726c5e0e10cd376298b9d5127.jpeg)
从上所述可得出: String 类的不可变真相,对于String类来说,不可变有两点含义:
1.字符串长度不可变,这是由于底层是char[]数组决定的。
2.字符串内容不可变,这是由于String类没有提供修改内容的方法导致的。
但是String又是可变的,怎么个变法呢?
下面我先抛出一个案例:
String str = "花夕";str = "花兮你好";System.out.println(str);
运行结果是:
![78f1896e655342334e2e01aa151786fd.png](https://i-blog.csdnimg.cn/blog_migrate/d0ec96dbc933bba390b4e873b27cadbc.jpeg)
由上面的案例可以看出str由“花夕”变成了“花夕你好”,这个str变了呀,其实懂String的人都知道,在声明str字符串的时候只是声明的一个地址而已,当你改变它的值的时候,不是重新给它赋值,而是重新申请了一个地址,存储”花夕你好”,srt引用指向存储”花夕你好”的地址而已。
上面都讲的是String定义的字符串不可变,内容不可变,但是我就是想尝试一下让它变化。
1.我用我学过的反射改变String定义的字符串内容,静观其变。
String str = "花夕";System.out.println("str未被修改的值是:" + str);//通过反射从方法区内存空间获取String类相关信息Class clazz = String.class;//获取String类里的value字段Field f = clazz.getDeclaredField("value");//绕过正常访问机制,增加访问权限,可以被修改f.setAccessible(true);//获取str属性值char[] chars = (char[]) f.get(str);//给str值重新赋值,改变的还是原来的char[]数组chars[0] = 'h';chars[1] = 'x';System.out.println("str被修改后的值" + str);
运行结果:
![606086cd392e894a7372dd3f4ffefd97.png](https://i-blog.csdnimg.cn/blog_migrate/1d3ab198caf170c224439e6f63ae133c.jpeg)
哇,str真的被修改过来了,好神奇哦。
2.我再看看String定义的字符串长度可变不?
我在上面的代码基础上加上一行代码
chars[2] = 'n';
运行结果:
![37c4c4d9b45488783eedac10c78fcb9c.png](https://i-blog.csdnimg.cn/blog_migrate/35f9fd92389cda5abd0edcafd961bd4e.jpeg)
直接报错,看来String定义的字符串长度是不可以变的哦。
看完这篇文章,你对String类到底可变有了一定认识了吧!
如果在找工作中,面试官问你String类可变不可变,你说一下。你就可以直接把这篇文章搬过去,相信面试官对你会刮目相看的!
【转发】和【关注】是对小强最大的支持!!!
![c870778de25d0dd2fad224cd1b4b9500.png](https://i-blog.csdnimg.cn/blog_migrate/2cc9abdbbff01ec410929abfbbe144bc.jpeg)