String str = "hello"; 和 String = new String("hello"); 的区别
SunRan

前言

1
2
String str = "hello"; 
String = new String("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
2
3
4
5
6
7
String str1 = "rush b";
String str2 = "rush b";

System.out.println(str1 == str2); // return true
System.out.println(str1.equals(str2)); // return true
System.out.println(System.identityHashCode(str1)); // return 1163157884
System.out.println(System.identityHashCode(str2)); // return 1163157884

str1str2 是完全不同的两个变量,在栈空间中地址是不同的,但是通过 System.identityHashCode发现他们其实也相同。如下图所示。

示例二

1
2
3
4
5
6
7
public class StringDemo {
public static void main(String[] args) {
String str1 = "ab";
String str2 = str1.intern();
System.out.println(str1 == str2); // true
}
}

代码非常简单,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 许可协议。转载请注明出处!
 评论