前言
1 | String str = "hello"; |
如上两个方法都可以得到我们想要的一个字符串,但是区别还是有的.
堆和常量池的关系
- 堆(Heap)
Java堆(Java Heap)是Java虚拟机所管理的内存中最大的一块。Heap是被所有线程共享的一块内存区域,在虚拟机启动时被创建。
Heap的唯一目的就是存放对象实例,几乎所有的对象实例都是在这里分配内存。
- 字符串常量池
在jdk1.7之前的版本中,字符串常量池是存在于永久代中,在永久代和堆中的地址是完全分离的,不会直接引用。
在jdk1.7+之后的版本中,字符串常量池被放在了堆中。
声明一个字符串
String Str1 = “hello”;
内存分布
对于str1来说,由于是常量赋值,str1直接指向字符串常量池中的数据,并且只有一份。
String str2 = new String(“hello”);
内存分布
String str2 = new String("ab");
在执行过程中,JVM首先在字符串常量池中查看字符串对象“ab”是否存在,若不存在,则现在字符串常量池中创建“ab”对象,然后再Heap中创建一个新的“ab”字符串对象。
若字符串常量池中已经存在了字符串对象“ab”,则直接在堆中创建一个字符串对象“ab”,不许在字符串常量池中创建对象,但是不管是那种方式,栈中的str2始终指向的是Heap中的字符串对象。
若字符串常量池中原本没有“ab”对象,String str2 = new String(“ab”);执行后会在字符串常量池和堆中各创建一个对象,即创建两个对象,若字符串常量池中已存在了“ab”对象,则只会在Heap中创建,即只创建了一个对象。
示例
示例一
1 | String str1 = "rush b"; |
str1
和 str2
是完全不同的两个变量,在栈空间中地址是不同的,但是通过 System.identityHashCode
发现他们其实也相同。如下图所示。
示例二
1 | public class StringDemo { |
代码非常简单,str1就是最普通的常量赋值,会直接在字符串常量池中创建出”ab”对象 str1调用intern方法得到返回值赋值给str2,intern方法会现在字符串常量池中检测是否已经存在”ab”字符串对象,若已经存在,直接把字符串常量池里”ab”对象的地址赋值给str2,所以str1==str2为true。
致谢
作者:saojiatete
链接:https://juejin.cn/post/6844904015830974472
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
- 本文标题:String str = "hello"; 和 String = new String("hello"); 的区别
- 本文作者:SunRan
- 创建时间:2022-01-08 18:15:54
- 本文链接:https://lksun.cn/2022/01/08/hello-和-String-new-String-hello-的区别/
- 版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!