Java中String创建对象过程及其运算原理

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_32625839/article/details/82634076

一、String类的常见问题解析

1.1、new String(“hello”)创建了几个对象

  不考虑其他因素,String b = new String("hello");这行代码到底创建了几个对象?

  情况一,创建了一个对象:

String a = "hello";
// 下面这一行代码创建了一个对象
String b = new String("hello");

  情况二,创建了两个对象:

// 下面这一行代码创建了两个对象
String b = new String("hello");
String a = "hello";

  所以,在以下代码片段中,综合其他代码的情况下,它可能是创建了一个,或者两个对象。如果不考虑其他代码,就这样一行运行,那么它就是和第二种情况一样,创建了两个对象

String b = new String("hello");

  因为在new String对象的时候,如果它需要的字符串在常量池中有了,那么这个String对象的成员变量value[]的值,就指向常量池中的对象,如果没有,就在常量池中新建一个字符串对象,然后再指向它,而String对象本身是在堆里的,下面进行详细的解释。


(1)创建了一个对象的情况(情况一)

  "hello"这个字符串,在创建对象之前,就在常量池中已经存在了

  (1)那么第一行代码String a = "hello";就是在常量池中创建了值为"hello"的对象,我们讨论的是第二行代码。
  (1)在第二行代码String b = new String("hello");是在里面创建了一个对象,引用b指向这个对象,而常量池中有值为"hello"这个对象,然后引用b指向的对象(new String("hello"))的成员变量char数组value[]指向常量池值为"hello"这个对象就行了,它就创建了一个对象new String("hello")

  下面进行验证,我们将下面输出语句打上断点,方便进行查看:
这里写图片描述
这里写图片描述
  在Debug模式下,可以看见变量ab的成员变量char数组value[]的地址是一样的,即是同一个char数组,代码String b = new String("hello");并没有为它的成员变量value[]创建新对象,而是指向了常量池中的值为hello的对象,即它只创建了一个对象。因此我们上面的分析是正确的。


(2)创建了两个对象的情况(情况二)

  "hello"这个字符串,创建对象之前,在常量池不存在

  (1)第一行代码String b = new String("hello");是在里面创建了一个对象,引用b指向这个对象,然后发现常量池没有值为hello的对象,于是进行创建,然后将这个String对象成员变量char数组value[],指向值为"hello"这个对象,这里一行代码就创建了两个对象。
  (2)然后第二行代码String a = "hello";直接将引用指向常量池中,值为"hello"的对象就行了。

  下面进行验证,同样为了方便进行查看,我们打上断点,注意代码顺序调换了:
这里写图片描述

  还是可以发现,变量ab的成员变量char数组value[]的地址是一样的,即是同一个char数组,在执行String b = new String("hello");有为它的成员变量value[]在常量池中创建新的对象,因为代码String a = "hello";的对象是在常量池中,但它却没有指向新的对象,它的成员变量,和第一行代码执行创建的对象的成员变量value[]的地址是一样的,即第一行代码执行的时候创建了两个对象。因此我们上面的分析是正确的。

注意:以上分析的时候,要知道String a = "hello";创建的对象是在常量池中,String b = new String("hello");创建的对象是在堆中。


1.2、判断各种字符串对象相等的情况

  如下代码:

String s = "12";
String s1 = "34";
String s2 = s + s1;
String s3 = "1234";
String s4 = "12" + "34";
String s5 = s + "34";
String s6 = "12" + new String("34");

// 第一题
System.out.println(s2 == s3); // false
// 第二题
System.out.println(s2 == s4); // false
// 第三题
System.out.println(s3 == s4); // true
// 第四题
System.out.println(s3 == s5); // false
// 第五题
System.out.println(s2 == s5); // false
// 第六题
System.out.println(s3 == s6); // false

以上题目你是否做对了呢?

做题之前,我们先了解一下规则:

(1)、Sun规定String类型运算的时new了StringBuilder对象,然后用append()方法追加字符串,最终以StringBuilder的toString()方法返回,而它的toString()方法是直接new了一个String对象返回的,那么 == 去比较两个String对象的地址,肯定是不相等的。

(2)、像"a"+"a"这种没有变量参与则在编译时就能确定,这种拼接会被优化,编译器直接帮你拼好,就不需要new的操作。

  于是就上面这些题目很容易得出结果了,注意第一题和第六题,因为也有变量参与了运算,这种在编译期也是无法确定的,也会根据规则(1)运算。

猜你喜欢

转载自blog.csdn.net/qq_32625839/article/details/82634076