完成职教集团网站建设,网站撤销备案,上海城建设计院网站,wordpress++压缩String类型的不可变众所周知#xff0c;String类型是不可变的#xff0c;一旦String对象被创建好了则这个字符串中的序列就不可改变。为什么String类型是不可变#xff1f;根据阅读源码可知#xff0c;String类是一个final类#xff0c;但是String不可变并不是因为它是一个…String类型的不可变众所周知String类型是不可变的一旦String对象被创建好了则这个字符串中的序列就不可改变。为什么String类型是不可变根据阅读源码可知String类是一个final类但是String不可变并不是因为它是一个final类final修饰的类只是不能被继承因为有字符串常量池这个东西如果String类能被继承就会出现安全问题。关于String不可变的原因是因为下面这句代码private final char value[];value负责存储String的值因为value是用final修饰的所以value的地址不能被改变(但是数组的值可以被改变)又因为在String类中并没有任何方法能够修改value的元素所以String是不可变的。但是在有的时候我们认为字符串改变了啊例如String shi; s world;s输出就会变成hi world这是因为重新给了s一个字符串对象相加后的对象和以前的对象不一样后面将会有代码演示。String类型真的不可变吗因为value是一个char数组他只是地址不可变其中的值是可变的String不可变是因为它没有提供给我们可以修改value的方法但是我们可以通过反射获取到value数组然后修改它的值这样可以实现“String的可变”。如下代码所示String s1 hello world;String s2 hello world;System.out.println(s1s2);System.out.println(s1);System.out.println(s2);Field field String.class.getDeclaredField(value);field.setAccessible(true);char[] value (char[])field.get(s1);value[1]i;value[2]i;value[3]i;value[4]i;System.out.println(s1s2);System.out.println(s1);System.out.println(s2);输出结果truehello worldhello worldtruehiiii worldhiiii world通过上面可以看出当我们改变s1的值时s2被改变了。关于String的一些常识如下代码String s1 hello world;String s2 hello world;String s3 hello world;String s4 new String(hello world);String s5 hello new String(world);String s6 new String(hello );String s7world;String s8 hello ;String s9s6s7;String s10s8s7;System.out.println(s1s2);System.out.println(s1s3);System.out.println(s1s4);System.out.println(s1s5);System.out.println(s4s5);System.out.println(s1s9);System.out.println(s1s10);System.out.println(s9s10);s1 s1!;System.out.println(s1);System.out.println(s2);System.out.println(s1s2);输出结果truetruefalsefalsefalsefalsefalsefalsehello world!hello worldfalse在String中使用new就新创建一个对象不论字符串常量池是否有它而s3和s10的区别在于在编译阶段就能确定s3因为s3指定了是hello 和world相结合而s10在编译阶段程序并不能确定s8和s7的值。String一些方法可能产生新的对象subString当subString截取的字符串就是本身的时候返回本身否则返回一个新声明的字符串。replace如果新字符和要替换的一样的话返回本身否则返回一个新声明的字符串。toCharArray返回一个新的字符数组对改数组进行修改不会对String产生任何影响。toString返回的是字符串本身trimtrim方法是返回String对象的一个副本该副本去除了原来字符串中的首部和尾部空白。但如果String对象首部和尾部没有空白的话则返回自身。否则调用subString方法返回一个崭新的String对象(真子串subString方法中说过)。关于String传参在开始String传参的时候先看看参数传递的两大类型值传递在我们进行参数传递的时候将实参拷贝一份传递过去所以在方法里面对其更改不会对原本的造成影响。引用传递在java中引用传递是拷贝该对象的地址传递过去如果在传递过去的地址对应的对象上进行修改就会影响原本的值。具体例子如下//自己声明的一个类class Ref {private String name;public void setName(String name) {this.name name;}public String getName(){return name;}Overridepublic String toString() {return Ref{ name name \ };}}public static void main(String[] args) {Ref ref new Ref();ref.setName(张三);int a5;String name 张三;change(ref);change(a);change(name);System.out.println(ref);System.out.println(a);System.out.println(name);}public static void change(Ref ref) {ref.setName(李四);}public static void change(int num) {num 18;}public static void change(String name) {name 李四;}//上面输出/*Ref{name李四}5张三*///将ref 的change函数改变如下public static void change(Ref ref) {Ref ref1 new Ref();ref ref1;ref.setName(李四);}/*运行Ref{name张三}5张三*/通过上面的例子我们发现对象的传递如果在方法里面进行了修改将会改变原本的值。但是要注意我们传递过去的只是地址如下图所示我们进行传递的时候将ref对象的地址拷贝一份传递过去(注意是拷贝一份),当我们没有对传递过去的形参地址进行修改的情况下对该形参进行修改都会影响原本的实参例如上面前面的change方法如果进行对形参的地址进行修改了的话将会和原本的实参断绝关系例如上面修改后的change方法。而上面的String的change就不用说了 name 李四相当于将name的地址修改为了字符串常量池中的李四对象。ref的存储结构.png通过上面的我们明白了什么是引用传递和值传递。关于String传参可能大家也有了答案。String传参的时候传递String对象所指向的地址但是由于String中没有方法能够对value数组进行修改所以我们在对String参数进行操作的时候都不会改变他的值很多情况下我们认为String的值变化了都是一种错觉。比如下面的replace方法public static void change(String name) {name.replace(张,李);}上面的代码很容易让我们产生name中的张换成了李的错觉但是其实并没有改变我们可以看一看replace的具体是怎么实现的replace.png我们可以看出repalce中并没有对原本value数组进行更改而是将value中的数组拷贝到buf中(需要替换的替换)然后返回一个new String。具体其他你认为String内容改变了的地方你可以阅读源码进行观察你就会发现其实都没有更改。关于String的其他内容可以点击查看