都说String是不可变的,但是究竟哪里不可变,是内容不可变还是什么不可变,又是怎么个变法,对此真的头大!为此我苦思不得其解,终于让我找到梗了!
首先我看了String源码,String被final修饰,而String类内的方法也都是被final修饰的。众所周知String底层是char数组,这个数组继而也是被final修饰。
一旦被final修饰,其初始化后内容是不可变的。数组被final修饰,数组长度是不可变的。
在IDE编辑器,Ctrl+N找到String类源码,再Ctrl+Alt+O,会出现以下信息,提示String是只读的,不能被修改。(这里的快捷键以自己配置的快捷键为主)
从上所述可得出: String 类的不可变真相,对于String类来说,不可变有两点含义:
1.字符串长度不可变,这是由于底层是char[]数组决定的。
2.字符串内容不可变,这是由于String类没有提供修改内容的方法导致的。
但是String又是可变的,怎么个变法呢?
下面我先抛出一个案例:
String str = "花夕";
str = "花兮你好";
System.out.println(str);
运行结果是:
由上面的案例可以看出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);
运行结果:
哇,str真的被修改过来了,好神奇哦。
2.我再看看String定义的字符串长度可变不?
我在上面的代码基础上加上一行代码
chars[2] = 'n';
运行结果:
直接报错,看来String定义的字符串长度是不可以变的哦。
看完这篇文章,你对String类到底可变有了一定认识了吧!
如果在找工作中,面试官问你String类可变不可变,你说一下。你就可以直接把这篇文章搬过去,相信面试官对你会刮目相看的!
推荐阅读:
为什么鲜有炫富的程序员?
开猿节流?可把我开心死了!
今日话题:String类到底可变不可变!