字符串“+”拼接与“=”比较调用String构造方法String的intern()方法

Posted 自由乐土

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了字符串“+”拼接与“=”比较调用String构造方法String的intern()方法相关的知识,希望对你有一定的参考价值。

一.String的“+”拼接与“=”比较

1.字符串的“=”操作

字符串的“=”操作比较的是左右操作引用指向的地址是否相同。
看以下代码:

		String str1 = "hello";	
        String str2 = "word";
        String str3 = "hello";
        System.out.println(str1 == str2);
        System.out.println(str1 == str3);
        System.out.println(str2 == str3);

解释:str1和str3指向的都是“hello”对象,而此对象存在于字符串常量池中且只有一份,所以str1和str3这两个引用指向的是同一对象,所以第二个输出是true;第一个和第三个输出是false;

2.字符串的“+”拼接操作

字符串的拼接有两种情况:

1).字符串常量之间拼接

此情况下,编译器会在编译期间自动将两个字符串常量合并为一个常量字符串

		String str1 = "hel"+"lo";  
        String str2 = "hello";
        System.out.println(str1 == str2);

解释:str1在加载时,会先将“hel”和“lo”进行拼接成“helllo”,然后在字符串常量池中检查,发现没有出现过“hello”,则在字符串常量池中创建一个“hello”对象,其地址赋值给str1,str2在加载时,拿着“hello”在字符串常量池检查发现已经有“hello”字符串对象了,直接将“hello”的地址赋值给str2,所以运行结果为true;

2).变量与字符串拼接或者多个变量进行拼接

先看一组代码:

		String str1 = "hel";                //①
        String str2 = str1+"lo";            //②
        String str3 = str1+"lo";            //③
        String str4 = "hello";             //④
        System.out.println(str2 == str3);  //⑤
        System.out.println(str3 == str4);  //⑥
        System.out.println(str2 == str4);  //⑦

猜猜运行结果是什么?
运行结果如下:

false
false
false

这是为什么呢?
刚学到这时,我也是一头雾水,百思不得其解。
原来在变量参与字符串拼接时会在底层创建一个StringBuilder对象,每次拼接都会被优化为调用一次StringBuilder的append方法。代码在加载第②行时,底层首先会创建一个StringBuilder对象,假设对象名字是stringBuilder,先用此对象append一次str1,即:stringBuilder.append(str1),遇到“+”,然后继续调用append方法去append(“lo”)。遇到“ ;”代表此行执行结束,在调用StringBuilder类的toString()方法将结果赋值给str2。第三行操作逻辑与第二行一致,值得注意的是每次都会创建一个StringBuilder对象,且最后都会调用toString()方法,所以str2和str3都是指向不同引用的对象,自然和str4也是不相等的。

特殊的“+=”操作呢?

字符串的+=操作和+操作并没有什么区别,只是在创建StringBuilder对象时会先append一次"+="符号的左操作数。
例如:

		String a = "hel";
        a += "lo";

执行时StringBuilder对象假设是stringBuilder会这样执行:stringBuilder.append(a).append(“lo”)

值得注意的是在循环中尽量不用String的“+”拼接操作,而使用的是StringBuilder对象的append( )方法。

二.String构造方法的调用

String的构造方法最常用的是传入一个字符串对象进行初始化。
例如:

String str = new String("hello");

那么它底层会怎么运行呢?
首先,采用构造方法new新建一个字符串对象时,JVM首先在字符串常量池中查找有没有“hello”这个对象,发现没有,其首先会在字符串常量池中创建一个“hello”字符串对象,然后再在堆上创建一个“hello”对象,让后将堆中这个“hello”字符串对象的引用赋值给str。而如果有的话,则不在池中再去创建“hello”这个对象了,直接在堆中创建一个“hello”字符串对象,然后将此对象的地址返回给str。

当构造方法遇到“+”操作

我们可能会遇到下面情形:

			String str1 = new String("hel") + new String("lo");
            String str2 = "hello";
            System.out.println(str1 == str2);

那么在第一行执行时是怎么运行的呢?
按照上面的逻辑来,调用构造方法时,先会检查字符串常量池中是否有“hel”对象,结果没有然后在字符串常量池中创建一个“hel”对象,然后对“lo”也是,在字符串常量池中创建一个“lo”对象,然后拼接,在堆中创建一个“hello”对象,将此对象的地址赋值给str1。

三.String的intern( )方法

intern( )的作用机理

有以下两个作用:
以下面代码为例:

            String str = new String("hel")+new String("lo");
            str = str.intern();

1.当字符串常量池中不存在“hello”这个字符串的引用时,将这个对象的引用加入常量池中,返回这个对象的引用。(注意:说的是引用即地址,地址都放大了字符串常量池中)
2.当常量池中存在“hello”这个字符串的引用时,直接返回这个对象的引用。

看下面练习:

			String str1 = new String("hello").intern();
            String str2 = "hello";

运行结果是 true;
解释:第一行在执行时,先new一个String对象,检查字符串常量池中没有“hello”,则在常量池中创建一个“hello”对象,继续执行代码遇到intern( )方法,此时再去常量池中查找发现存在“hello”对象,然后将字符串常量池中的“hello”对象的引用(即地址)返回给str1.。第二行执行时也是直接将字符串常量池中的“hello”引用赋值给str2,所以结果为true;

最后看一下下面的题,看看自己能否全对:

			String str1 = new String("abc");
            String internStr1 = str1.intern();
            String poolStr1 = "abc";
            System.out.println(str1 == internStr1);
            System.out.println(str1 == poolStr1);
            System.out.println(internStr1 == poolStr1);
            
            String str2 = new String("hel")+("lo");
            String internStr2 = str2.intern();
            String poolStr2 = "hello";
            System.out.println(str2 == internStr2);
            System.out.println(str2 == poolStr2);
            System.out.println(internStr2 == poolStr2);

答案:

false
false
true

true
true
true

以上是关于字符串“+”拼接与“=”比较调用String构造方法String的intern()方法的主要内容,如果未能解决你的问题,请参考以下文章

字符串“+”拼接与“=”比较调用String构造方法String的intern()方法

字符串“+”拼接与“=”比较调用String构造方法String的intern()方法

字符串拼接‘+’实现

Java 字符串比较拼接问题

StringBuffer类常用方法

C++中的STL(超详细的操作)