`

String对象操作符“+”解析

    博客分类:
  • J2SE
 
阅读更多
javac Test 编译文件
javap -c Test 查看虚拟机指令

实验一:纯字符串
public class Test {
    public static void main(String args[]) {
        String str = "a";
    }
}
 // 将字符串 a 存入常数池
  0: ldc #2; //String a
  // 将引用存放到 1 号局部变量中
  2: astore_1
  3: return

实验二:纯字符串相加
public class Test {
    public static void main(String args[]) {
        String str = "a" + "b";
    }
}
 // 将字符串 ab 压入常数池
  0: ldc #2; //String ab
  2: astore_1
  3: return

实验二可以很明显地看出,编译器在编译时产生的字节码已经将 "a" + "b" 优化成了 "ab",
同理多个字符串的相加也会被优化处理,需要注意的是字符串常量相加
实验三:字符串与自动提升常量相加
public class Test {
    public static void main(String args[]) {
        String str = "a" + (1 + 2);
    }
}
 // 将字符串 a3 压入常数池
  0: ldc #2; //String a3
  2: astore_1
  3: return

通过虚拟机指令可以看出,1 + 2 自动提升后的常量与字符串常量,虚拟机也会对其进行优化。

实验二、实验三结论:常量间的相加并不会引起效率问题

实验四:字符串与变量相加
public class Test {
    public static void main(String args[]) {
        String s = "b";
        String str = "a" + s;
    }
}
 
// 将字符串 b 压入常数池
  0: ldc #2; //String b
  // 将引用存放到 1 号局部变量中
  2: astore_1
  // 检查到非常量的相加,这时创建 StringBuilder 对象
  3: new #3; //class java/lang/StringBuilder
  // 从栈中复制出数据,即把字符串 b 复制出来
  6: dup
  // 调用 StringBuilder 的初始构造
  7: invokespecial #4; //Method java/lang/StringBuilder."<init>":()V
  // 将字符串 a 压入常数池
  10: ldc #5; //String a
  // 调用 StringBuilder 的 append 方法,把字符串 a 添加进去
  12: invokevirtual #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
  // 从 1 号局部变量中加载数据引用
  15: aload_1
  // 调用 StringBuilder 的 append 方法,把字符串 b 添加进去
  16: invokevirtual #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
  // 调用 StringBuilder 的 toString 方法
  19: invokevirtual #7; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
  // 将 toString 的结果保存至 2 号局部变量
  22: astore_2
  23: return

实验四可以看出,非常量字会串相加时,由于相加的变量中存放的是字符串的地址引用,
因为在编译时无法确切地知道其他具体的值,也就没有办法对其进行优化处理,这时为了
达到连接的效果,其内部采用了 StringBuilder 的机制进行处理(JDK 5 中新增的,我
这里没有 JDK 1.4,估计在 JDK 1.4 下采用的是 StringBuffer),将他们都 append
进去,最后用 toString 输出。

若 s 为其他类型时,比如:int 类型,也是采用同种方式进行处理。

同理,根据实验二的结果,在 String str = "a" + "b" + s; 时,先会优化成 "ab" 再与
s 根据实验四的方式进行处理,这时 StringBuilder 仅调用了两次 append 方法。

如果是 String str = "a" + s + "b"; 这种形式的就没办法优化了,StringBuilder 得调
用三次 append 方法。

实验四的结论表明,字符串与变量相加时在内部产生了 StringBuilder 对象并采取了一定
的操作。

如果只有一句 String str = "a" + s; 这样子的,其效率与
String str = new StringBuilder().append("a").append(s).toString();
是一样的。

一般所说的 String 采用连接运算符(+)效率低下主要产生在以下的情况中:
public class Test {
    public static void main(String args[]) {
        String s = null;
        for(int i = 0; i < 100; i++) {
            s += "a";
        }
    }
}
 每做一次 + 就产生个 StringBuilder 对象,然后 append 后就扔掉。下次循环再到达时重
新产生个 StringBuilder 对象,然后 append 字符串,如此循环直至结束。

如果我们直接采用 StringBuilder 对象进行 append 的话,我们可以节省 N - 1 次创建和
销毁对象的时间。
分享到:
评论

相关推荐

    编写类String的构造函数

    根据给定的文件信息,我们将深入探讨如何实现一个自定义的`String`类,并重点讲解其构造函数、析构函数、拷贝构造函数以及赋值操作符。在C++编程语言中,这些成员函数对于正确地管理动态分配的内存至关重要。 ### ...

    String对象的拓展-好用的JS验证程序

    `split(separator[, limit])`方法在字符串处理中也十分常见,它可以根据分隔符将字符串分割成数组,这对于解析CSV或自定义格式的数据非常有用。 `concat(string2[, string3[, ...]])`用于合并字符串,而`includes...

    用java写一个简单计算器

    用户可以通过点击数字按钮输入数字,并通过操作符按钮选择数学运算类型。最后通过点击“=”按钮得到计算结果。 #### 三、技术栈 - **Java**:面向对象的编程语言。 - **Swing**:Java用于构建图形用户界面的API。 ...

    解析类,从文件中解析成对象

    "解析类,从文件中解析成对象"这个标题所指的知识点,主要涉及到C++编程中的文件I/O操作、字符串处理、自定义解析逻辑以及面向对象编程原则。下面将详细阐述这些关键点。 首先,C++的文件I/O操作是基础,它允许程序...

    rxjava常用操作符

    ### RxJava常用操作符 #### 一、Observable的创建 RxJava的核心概念之一是`Observable`,它代表了数据源,能够发出数据项序列。在实际应用中,我们需要通过不同的方式来创建`Observable`,从而启动事件流。下面将...

    java内存分配和String类型的深度解析Java开发J

    使用`+`操作符连接字符串会创建新的String对象,如果频繁操作,会产生大量临时对象,消耗内存。为优化性能,可以使用StringBuilder或StringBuffer类,它们提供了append方法,可以在已有字符串基础上添加内容,无需...

    String,number,String+number的Comparator排序

    在Java中,这些类型的比较可以直接使用`, `&gt;`, `, `&gt;=`操作符,或者使用`compareTo()`方法。如果需要自定义排序规则,如按绝对值排序或负数在前正数在后,可以创建`Comparator&lt;Number&gt;`。同样,`compare()`方法是...

    String&StringBuffer&StringBuilder三者之间的区别-经典解析.doc

    在Java编程语言中,String、StringBuffer和StringBuilder都是...在进行字符串拼接时,特别是循环或递归操作中,避免使用String的`+`操作符,因为它会频繁创建新对象,而应优先考虑使用StringBuffer或StringBuilder。

    java基础简单计算器

    ### Java基础简单计算器知识点解析 #### 一、项目概述 本项目主要介绍了一个基于Java语言实现的简单计算器程序。该程序能够接收用户输入,并完成基本的数值计算功能。通过本项目的学习,我们可以深入了解Java的...

    JavaScript中的比较操作符&gt;、&lt;、&gt;=、&lt;=介绍

    - 当比较操作符的两边为对象时,JavaScript首先会尝试将对象转换成数值(Number),如果转换失败,则会转换成字符串(String)。 - 如果两边都转换成了字符串,则按照字符串中的字符在编码表中的顺序进行比较。 -...

    String容量大小区分

    需要注意的是,直接使用`+`操作符进行字符串拼接会导致频繁创建新的String对象,尤其是当拼接操作嵌套在循环中时,可能会导致性能问题和内存泄漏。为了解决这个问题,可以采用`StringBuilder`或`StringBuffer`类来...

    String和string区别以及string详解.doc

    标题与描述中提到的知识点是关于C#编程语言中`String`与`string`的区别,以及`string`类型的深入解析。以下是对这些知识点的详细解释: ### `String`与`string`的区别 #### 1. **位置与来源** - `String`是.NET ...

    “java高分面试指南”-25分类227页1000+题50w+字解析.pdf

    instanceof关键字是Java中的一个重要操作符,用于在运行时检查对象是否为特定类或其子类的实例。面试官往往通过询问这一关键字的用法,来评估面试者对于Java类型系统和多态性的理解程度。 在类型转换方面,Java中...

    冠字号FSN文件解析成对象 与 对象转为FSN文件

    本话题关注的是如何使用Java处理FSN文件,将其解析成对象并由对象转换回FSN文件。以下是关于这个主题的详细知识点: 1. **FSN文件格式**: 冠字号文件通常包含每张纸币的冠字号码、交易时间、交易金额、设备编号等...

    c++ string转换double

    首先,通过 `new` 操作符分配了一个长度为 `str.length()` 的字符数组 `ch`。注意,这里没有为字符串末尾添加空字符,这可能会导致后续调用 `atof` 函数时的行为未定义。 **3. 复制字符串** 接着,使用循环将 `std...

    Java上海汉得笔试题+答案解析

    - **对象比较:**`==` 操作符用于比较两个对象是否指向同一个内存地址,即它们是否为同一个对象。对于 `Long` 类型的对象,即使值相同,如果一个对象是通过 `new` 关键字创建的,那么即使另一个对象的值相同但未...

    Java String初始化String域例题解析

    3. "==" 操作符比较的是地址,而不是值。 接下来,我们再看一个例子: ``` String s1 = "aaa"; String s2 = "bbb"; String s3 = "aaabbb"; System.out.println(s3 == s1 + s2); //false System.out.println(s3 == ...

    c++中由类名(string)创建这个类对象(RTTI)

    - `typeid`操作符可以返回一个`type_info`对象,它包含了类型的名字和其他元数据。例如: ```cpp if (typeid(*basePtr) == typeid(Derived)) { // basePtr指向的是Derived类型的对象 } ``` - `typeid`也可以...

    计算string类型算式的结果

    1. **字符串解析**:首先,我们需要将字符串如"1+1"解析成可操作的元素。这通常通过分隔符分割字符串完成,例如用空格或特定运算符作为分隔符。在本例中,我们可以假设字符串仅包含数字和单个运算符,这简化了解析...

Global site tag (gtag.js) - Google Analytics