String引用的值改变了为什么赋值的值没变

代码跟运行结果如下

 public static void main(String[] agrs){
        String s1 = new String("aaa");
        String s2 = s1;

        System.out.println("s1=" + s1);
        System.out.println("s2=" + s2);
        s1 = "bbb";
        System.out.println("s1=" + s1);
        System.out.println("s2=" + s2);

    }
s1=aaa
s2=aaa
s1=bbb
s2=aaa

引用https://www.zhihu.com/question/20618891
string是不可变的引用类型,赋值时等于是将新的字符串值得引用指向到变量名,每写一个新的字符串值就会在内存开辟新的地址存放这个值

String s2 = s1; 是拷贝赋值,不是引用。

编译器优化引起的,new一个固定字符串编译器按常量处理,s1重新赋值后指向另外一个内存区域,s2还是指的aaa这个常量区

首先

 String s1 = new String("aaa");

这条语句是在静态区内创建了一个aaa的常量,然后在创建s1指向'aaa'常量

 String s2 = s1;

这条语句指的是s2指向'aaa'的地址
虽然s1被改,但s2并没有重新指向新的地址

字符串是不变的(immutable)
s1 = "bbb";
不能改变原来s1的内容为bbb
相反,它创建了一个新的字符串(无论是在常量池还是堆栈),并且让s1指向了这个新的字符串。
而s2还指向bbb

简单来说就是s2是已经把s1的内容存在自己的内存区域,s1和s2分别有两个地址,打印重新给s1赋值只是在s1的地址的内容进行修改

s1 s2 都只是常量aaa的“名字”。当执行s1=bbb时 s1又被bbb用来当"名字"。此时aaa的名字就只剩s2,所以此时打印出来的是原来内容

程序有上往下执行,当执行第一个赋值的时候S1的值给了S2,当S1发生了改变是改变了地址,所以S2的值不会随之改变。

之所以没有被改变和String的构造方法有关系,基本上String都是拷贝赋值的。

下面链接说的已经很清楚了,可以读一下。
https://www.cnblogs.com/JavaSubin/p/5450849.html

赋值和赋址本质上都是赋值(只是对于引用类型值就是地址)
对于字面量在编译后字节码总是从常量池进行引用,在编译后相同字面量在运行时引用是一样的

string s1 = new string("aaa"); 在内存空间创建字符串“aaa”,并创建字符串引用变量s1指向它;
string s2 = s1; 创建字符串引用变量s2,赋值s1,表示s2和s1指向相同的内存空间;
s1 = "bbb"; 相当于在内存空间创建字符串常量“bbb”, 用已有的s1指向它,现在s1不在指向原来的"aaa";
而s2的指向没有变,还是指向"aaa". 所以输出的内容还是aaa。

如果想让s2指向的内存和s1一致,应该在修改s1的指向之后再做一次 s2=s1;
这时内存空间中的字符串“aaa”已经没有引用指向它,在java中会被垃圾回收站回收,但c++没有垃圾回收功能,可能会造成内存泄漏

图片说明

当String s1=new String(“aaa”)时,是在堆内存中开辟一块空间存储aaa,再在绽内存中开辟一块空间放变量s1,然后让s1指向aaa,改变s1的值,只是在栈内存中再声明一个产量让其指向aaa

第一次的时候 s1和s2的引用是想同的 值肯定相同

第二次你对s1再次赋值了 s2还是引用的原来的值

所以不一样了