写点什么

Java 学习笔记——String,java 程序开发实战教程在线

用户头像
极客good
关注
发布于: 刚刚

}


}


结果为 helloworld,这里 s 对应的值从 hello 变成了 helloworld,那么为什么还说字符串一旦被赋值就不能被改变呢?


当我们使用 String s = “hello”;语句创建字符串的时候,首先会去常量池中查找,如果有,就返回这个常量的地址,如果没有,在常量池中创建并返回。


比如这里的“hello”,一开始是没有的,所以要先创建,然后返回一个地址,比如 0x001


下一次,如果 String ss = “hello”;的时候,ss 指向的也会是这个 0x001 的地址



我们可以用==来验证一下


String s = "hello"; //常量池中没有常量"hello"就创建,假设地址值为 0x001


String s1 = "hello"; //在常量池中查找到"hello",因此 s1 也指向地址 0x001


System.out.println(s==s1); //地址值相同,所以返回的结果为 true


之后 s = s+“world”; 语句中出现了“world”,同样要在常量池中创建



现在需要将“hello”与“world”进行拼接,这里的拼接会开辟出一个新的地址空间,然后将拼接后的”helloworld“放入



之前的变量 s 会重新指向这个新的地址 0x003,而不是原先的 0x001


所以说字符串一旦被创建,值就不可改变


这里的值指的字符串本身的值,而不是地址值


那么现在需要思考下一个问题

[](

)String s = new String(“hello”)和 String s = “hello”;的区别是什么?


package test.StringDemo;


public class demo2 {


public static void main(String[] args) {


String s1 = new String("hello");


String s2 = "hello";


System.out.println(s1 == s2); // false


System.out.println(s1.equals(s2)); //true


}


}


这里可以发现 s1 与 s2 的内容相同,但是地址不同


这里需要确认三件事情


  1. ==比较引用数据类型比较的是地址值

  2. equals 默认比较的是地址值,但是由于 String 类中重写了该方法,所以比较的是内容

  3. String s = new String(“hello”) 会在堆内存中创建对象


知道了这三点,再来看具体的操作过程


首先是 String s1 = new String(“hello”);


new String()会在堆内存中创建对象,而引用变量 String s1 则会在栈里面被创建,然后 s1 指向堆内存中被创建的 String 对象


”hello“也会在常量池中被创建,然后 new String()创建的 String 对象会指向”hello“的地址,比如 0x001,而 String 对象本身在堆内存中的地址,假设为 0x0001,两个地址是不一样的


因此,这里的引用变量 s1 指向的是堆内存中 String 对象地址 0x0001,而不是直接指向常量池中”hello“的地址 0x001



String s2 = “hello”;中的引用变量 s2 在栈里面被创建后,就可以直接指向常量池中”hello“的地址 0x001


所以才会出现 s1 与 s2 的内容相同,但是地址不同的情况


[](

)字符串常量相加与变量相加的区别


  1. 字符串如果是变量相加,是先开辟空间,然后再拼接

  2. 字符串如果是常量相加,是先加,然后再去常量池里找,如果找到了就返回,如果找不到就创建


package test.StringDemo;


public class demo4 {


public static void main(String[] args) {


String s1 = "hello";


String s2 = "world";


String s3 = "helloworld";


System.out.println(s3==(s1+s2)); //false


System.out.println(s3==("hello"+"world")); //true


}


}


s3==(s1+s2)的结果是 false,是因为变量相加是先在常量池中开辟空间,然后将拼接后的字符串放入开辟的空间之中,因此地址会改变。


s3==(“hello”+“world”)的结果是 true,是因为常量相加,是先拼接,然后在常量池中查找,是否有拼接后的字符串,如果有就返回这个地址值,如果没有才会创建新的空间。因为之前 s3 已经创建了”helloworld“字符串,所以返回的是 s3 指向的这个地址。因此地址相同。


那么还有一个问题,这里我们通过 s1+s2 的方式在常量池中创建了一个字符串”helloworld“,假设这个地址是 0x001。那么原先 s3 指向的字符串同样是”helloworld“,假设地址是 0x002。


这里的内容相同,但是地址不同,如果此时我再创建一个呢?比如


package test.StringDemo;


public class demo4 {


public static void main(String[] args) {


String s1 = "hello";


String s2 = "world";


String s3 = "helloworld";


String s4 = s1+s2;


String s5 = "helloworld";


}


}


s5 会在常量池中查找"helloworld",如果找到就返回地址,可是这里不仅找到了,而且一下子找到了两个,那么会返回哪个地址呢?


package test.StringDemo;


public class demo4 {


public static void main(String[] args) {


String s1 = "hello";


String s2 = "world";


String s3 = "helloworld";


String s4 = s1+s2;


String s5 = "helloworld";


System.out.println(System.identityHashCode(s3)); //第一行


System.out.println(System.identityHashCode(s4)); //第二行


System.out.println(System.identityHashCode(s5)); //第三行


}


}第一行与第三行返回的值相同,说明 s5 优先指向的地址是 s3 一开始就创建的


【一线大厂Java面试题解析+核心总结学习笔记+最新架构讲解视频+实战项目源码讲义】
浏览器打开:qq.cn.hn/FTf 免费领取
复制代码


地址

用户头像

极客good

关注

还未添加个人签名 2021.03.18 加入

还未添加个人简介

评论

发布
暂无评论
Java学习笔记——String,java程序开发实战教程在线