Java 定义字符串时:String 和 new String() 的区别

版权声明:本文为博主原创文章,同步今日头条号:Java云笔记。转载请附上博文链接: https://blog.csdn.net/weixin_44259720/article/details/88237822

首先,我们需要明白三个词的概念:栈,堆,字符串常量池。

  • 栈区:存放的是基本类型和引用类型的引用地址,不能存对象;
  • 堆区:存放对象;
  • 字符串常量池:在方法区,是独立于栈和堆的存储空间,用于存放常量;

然后,我们分别简述下他们的实现过程:

1. String str1 = "Jimmy" :

首先 JVM 在栈区创建 str1 的引用,然后在"字符串常量池"中寻找是否已经存在其指向的内容为"Jimmy"的对象,如果"字符串常量池"中有,则直接将 str1 的引用指向常量池中的"Jimmy"对象;如果没有,则创建一个新的,然后将 str1 的引用指向"字符串常量池"中的对象;

  • 如果后来又定义了字符串变量 str2 = "Jimmy",则直接将 str2 的引用指向"字符串常量池"中已经存在的"Jimmy"对象,不再重新创建新的对象;
  • 当 str1 进行了新的赋值(如:str1 = "Jim"),则 str1 将不再指向"Jimmy",而是重新指向"字符串常量池"中的 "Jim"。
  • 此时如果定义 String str3 = "Jim",进行 str1 == str3 操作,返回值为true,因为他们的值一样,地址一样;但是如果内容为 "Jim" 的 str1 进行了字符串的连接 str1 = str1+"my",此时 str1 指向的是在堆中新建的内容为"Jimmy"的对象,即此时进行str1 == str2,返回值 false,因为他们的地址不一样。

上述分析的案例:

@Test
public void test(){
    String str1 = "Jimmy";
    String str2 = "Jimmy";
		
    System.out.println(str1 == str2);        // true
		
    str1 = "Jim";
    String str3 = "Jim";
		
    System.out.println(str1 == str3);        // true
		
    str1 = str1+"my";
		
    System.out.println("str1 = " + str1);    // str1 = "Jimmy"
    System.out.println(str1 == str2);        // false
}

2. String str1 = new String("Jimmy") :

直接在堆中创建对象(new一个对象,可以理解为“我需要一个全新的对象”);

  • 如果又有 String str2 = new String("Jimmy"),那么 str2 不会指向之前的对象,而是重新创建一个新的对象并指向它,两个对象的地址不一样,所以此时 str1 == str2 返回值是 false;
  • 而此时 str1.equals(str2) 返回值是 true,因为 String 重写了 Object 的 equals() 方法,比较的是内容是否相同。

上述分析的案例:

@Test
public void test(){
    String str1 = "Jimmy";
    String str2 = new String("Jimmy");
		
    System.out.println(str1 == str2);         // false
    System.out.println(str1.equals(str2));    // true
}

更多精彩,请关注我的"今日头条号":Java云笔记
随时随地,让你拥有最新,最便捷的掌上云服务

猜你喜欢

转载自blog.csdn.net/weixin_44259720/article/details/88237822