Java 字符串拼接原理分析

导读:本篇文章讲解 Java 字符串拼接原理分析,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

Java 字符串拼接原理分析

对于常量做字符串拼接操作时,对于编译期就能确定的值,编译器会将值合并。

【示例】常量做字符串拼接

public class Test {
	public static void main(String[] args) {
		test01();
		test02();
	}
	/**
	 * 直接字符串常量拼接,对于编译期就能确定的值,编译器会将值合并
	 * String hw = "hello" + "world";
	 * 我们反编译字节码文件,就会将看到 : String hw = "helloworld";
	 * 
	 * 所以hw == helloWorld 输出true
	 */
	public static void test01() {
		String hw = "hello" + "world"; // 等于:String hw = "helloworld";
		String helloWorld = "helloworld";
		System.out.println(hw == helloWorld); // 输出:true
	}
/**
	 * String hw = h + "world";虽然包含变量h的运算,但是编译器
	 * 对final变量在编译期能确定其值,会发生宏替换,即:h变量替换成其值"hello",
	 * 然后编译器会对直接量字串直接合并
	 * String hw = h + "world";在编译完后就变成了 String hw = "helloworld";
	 * 
	 * 所以hw == helloWorld 输出true
	 */
	public static void test02() {
		final String h = "hello"; // final修饰的是常量
		String hw = h + "world"; // 等于:String hw = "helloworld";
		String helloWorld = "helloworld";
		System.out.println(hw == helloWorld); // 输出:true
	}
}
/**
 * 使用“+”连接符完成字符串拼接操作的底层分析(重点)
 * 情况一:两个字符串都是常量时,使用“+”来完成拼接操作
 *    底层:因为常量保存的内容不可改变,也就是编译时期就能确定常量的值,因此为了提高字符串的拼接效率,所以就在编译时期就完成了拼接操作。
 *    例如1:String str = "hello" + "world"; 编译之后:String str = "helloworld";
 *    例如2:final String STR1 = "hello"; final String STR2 = "world"; String str = STR1 + STR2; 编译之后:String str = "helloworld";
 */
public class TestStringConcatPrinciple01 {
    /**
     * 情况一:两个字符串都是常量时,使用“+”来完成拼接操作
     */
    public static void main(String[] args) {
        String str = "hello" + "world"; // 编译之后:String str = "helloworld";
        System.out.println(str);
    }
}

在jd-gui中,将上面的代码进行反编译得到结果如下:
在这里插入图片描述

/**
 * 使用“+”连接符完成字符串拼接操作的底层分析(重点)
 * 情况一:两个字符串都是常量时,使用“+”来完成拼接操作
 *    底层:因为常量保存的内容不可改变,也就是编译时期就能确定常量的值,因此为了提高字符串的拼接效率,所以就在编译时期就完成了拼接操作。
 *    例如1:String str = "hello" + "world"; 编译之后:String str = "helloworld";
 *    例如2:final String STR1 = "hello"; final String STR2 = "world"; String str = STR1 + STR2; 编译之后:String str = "helloworld";
 */
public class TestStringConcatPrinciple02 {
    /**
     * 情况一:两个字符串都是常量时,使用“+”来完成拼接操作
     */
    public static void main(String[] args) {
        final String STR1 = "hello";
        final String STR2 = "world";
        String str = STR1 + STR2;
        // 以上三行代码,在编译之后的结果就是:String str = "helloworld";
        System.out.println(str);
    }
}

在jd-gui中,将上面的代码进行反编译得到结果如下:
在这里插入图片描述对于变量做字符串拼接操作时,由于相加的变量中存放的是字符串的地址引用,因为在编译时无法确切地知道其他具体的值,也就没有办法对其进行优化处理,这时为了达到连接的效果,其内部采用了StringBuilder的机制进行处理(JDK1.5中新增的,我这里没有JDK1.4,估计在JDK1.4下采用的是StringBuffer),将他们都 append进去,最后用toString 输出。

【示例】变量做字符串拼接操作

public class Test {
/**
	 * hw在编译期并不能确定值,因为str是变量,JVM在运行期才能确定其值。
	 * 在运行期时,进行字串拼接生成新的字串对象,通过javap -c Test查看虚拟机
	 * 指令,我们发现“String hw = str + "world";”其实等效于:
	 * StringBuilder sb = new StringBuilder();
	 * sb.append(str);
	 * sb.append("world");
	 * String hw = sb.toString();
	 *
	 * 所以hw == helloWorld 输出false
	 */
	public static void main(String[] args) {
		String str = "hello";
		String hw = str + "world";
		String helloWolrd = "helloworld";
		System.out.println(hw == helloWolrd); // 输出:false 
	}
}
/**
 * 情况二:其中一个为字符串变量时,使用“+”来完成拼接操作
 *    底层:因为编译时期无法确定变量的值,因此其中一个为字符串变量的拼接操作,那么肯定不是在编译时期完成,而是在运行时期来完成的,并且实现步骤如下。
 *    例如:分析“String hw = str + "world"”代码的底层实现过程
 *      第一步:创建一个StringBuilder对象,用于字符串的拼接操作。
 *         --> StringBuilder sb = new StringBuilder();
 *      第二步:调用sb对象的append()方法,用于拼接str字符串。
 *         --> sb.append(str);
 *      第三步:调用sb对象的appen d()方法,用于拼接"world"。
 *         --> sb.append("world");
 *      第四步:调用sb对象的toString()方法,然后再去做赋值操作
 *         --> String hw = sb.toString();
 */
public class TestStringConcatPrinciple03 {

    public static void main(String[] args) {
        String str = "hello";
        String hw = str + "world";
        System.out.println(str);
    }
}

在jd-gui中,将上面的代码进行反编译得到结果如下:
在这里插入图片描述javap -c Test查看虚拟机指令
在这里插入图片描述

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/85598.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!