在Java中连接字符串时是使用+号还是使用StringBuilder

跨马翻译工具核心技术解析与多场景应用测评 图片翻译技术通过OCR识别与机器翻译的融合,实现了视觉内容到目标语言的精准转换。其核心原理在于多模态信息处理,先提取图像中的文本特征,再结合语义分析进行跨语言转换。这类技术在跨境电商、学术研究、旅游等场景具有重要价值,能有效解决语言障碍带来的信息断层问题。以跨马翻译为代表的先进工具采用视觉-文本对齐算法,在保持原文排版的同时提升翻译准确率,其专业模式支持23个垂直领域术语库,实测手写体识别准确率达91%。对于开发者而言,通过API集成可实现批量图片翻译自动化,但需注意处理超小字号文本等现存技术瓶颈。 阅读详情

    字符串是Java程序中最常用的一种数据结构之一。在Java中的String类已经重载了"+"。也就是说,字符串可以直接使用"+"进行连接,如下面代码所示:

String s = "abc" + "ddd";


但这样做真的好吗?当然,这个问题不能简单地回答yes or no。要根据具体情况来定。在Java中提供了一个StringBuilder类(这个类只在J2SE5及以上版本提供,以前的版本使用StringBuffer类),这个类也可以起到"+"的作用。那么我们应该用哪个呢?

    下面让我们先看看如下的代码:

package string;
  
  
public class
 TestSimplePlus
  
{
      
public static void
 main(String[] args)
      
{
          String s 
= "abc"
;
          String ss 
= "ok" + s + "xyz" + 5
;
          System.out.println(ss);
      }

  }


上面的代码将会输出正确的结果。从表面上看,对字符串和整型使用"+"号并没有什么区别,但事实真的如此吗?下面让我们来看看这段代码的本质。
我们首先使用反编译工具(如jdk带的javap、或jad)将TestSimplePlus反编译成Java Byte Code,其中的奥秘就一目了然了。在本文将使用jad来反编译,命令如下:

jad -o -a -s d.java TestSimplePlus.class
 
反编译后的代码如下:

package string;

import
 java.io.PrintStream;

public class
 TestSimplePlus
{
    
public
 TestSimplePlus()
    
{
    
//
    0    0:aload_0         
    
//
    1    1:invokespecial   #8   <Method void Object()>
    
//    2    4:return          

    }


    
public static void main(String args[])
    
{
      String s 
= "abc"
;
    
//
    0    0:ldc1            #16  <String "abc">
    
//    1    2:astore_1        

      String ss = (new StringBuilder("ok")).append(s).append("xyz").append(5).toString();
    
//
    2    3:new             #18  <Class StringBuilder>
    
//
    3    6:dup             
    
//
    4    7:ldc1            #20  <String "ok">
    
//
    5    9:invokespecial   #22  <Method void StringBuilder(String)>
    
//
    6   12:aload_1         
    
//
    7   13:invokevirtual   #25  <Method StringBuilder StringBuilder.append(String)>
    
//
    8   16:ldc1            #29  <String "xyz">
    
//
    9   18:invokevirtual   #25  <Method StringBuilder StringBuilder.append(String)>
    
//
   10   21:iconst_5        
    
//
   11   22:invokevirtual   #31  <Method StringBuilder StringBuilder.append(int)>
    
//
   12   25:invokevirtual   #34  <Method String StringBuilder.toString()>
    
//   13   28:astore_2        

      System.out.println(ss);
    
//
   14   29:getstatic       #38  <Field PrintStream System.out>
    
//
   15   32:aload_2         
    
//
   16   33:invokevirtual   #44  <Method void PrintStream.println(String)>
    
//   17   36:return          

    }

}



读者可能看到上面的Java字节码感到迷糊,不过大家不必担心。本文的目的并不是讲解Java Byte Code,因此,并不用了解具体的字节码的含义。

使用jad反编译的好处之一就是可以同时生成字节码和源代码。这样可以进行对照研究。从上面的代码很容易看出,虽然在源程序中使用了"+",但在编译时仍然将"+"转换成StringBuilder。因此,我们可以得出结论,在Java中无论使用何种方式进行字符串连接,实际上都使用的是StringBuilder。
那么是不是可以根据这个结论推出使用"+"和StringBuilder的效果是一样的呢?这个要从两个方面的解释。如果从运行结果来解释,那么"+"和StringBuilder是完全等效的。但如果从运行效率和资源消耗方面看,那它们将存在很大的区别。

    当然,如果连接字符串行表达式很简单(如上面的顺序结构),那么"+"和StringBuilder基本是一样的,但如果结构比较复杂,如使用循环来连接字符串,那么产生的Java Byte Code就会有很大的区别。先让我们看看如下的代码:

package string;
  
  
import java.util.*
;
  
  
public class
 TestComplexPlus
  
{
      
public static void
 main(String[] args)
      
{
          String s 
= ""
;
          Random rand 
= new
 Random();
          
for (int i = 0; i < 10; i++
)
          
{
              s 
= s + rand.nextInt(1000) + " "
;
          }

          System.out.println(s);
      }

  }



上面的代码返编译后的Java Byte Code如下:

package string;

import
 java.io.PrintStream;
import
 java.util.Random;

public class
 TestComplexPlus
{

    
public
 TestComplexPlus()
    
{
    
//
    0    0:aload_0         
    
//
    1    1:invokespecial   #8   <Method void Object()>
    
//    2    4:return          

    }


    
public static void main(String args[])
    
{
        String s 
= ""
;
    
//
    0    0:ldc1            #16  <String "">
    
//    1    2:astore_1        

        Random rand = new Random();
    
//
    2    3:new             #18  <Class Random>
    
//
    3    6:dup             
    
//
    4    7:invokespecial   #20  <Method void Random()>
    
//    5   10:astore_2        

        for(int i = 0; i < 10; i++)
    
//
*   6   11:iconst_0        
    
//
*   7   12:istore_3        
    
//*   8   13:goto            49

         s = (new StringBuilder(String.valueOf(s))).append(rand.nextInt(1000)).append(" ").toString();
    
//
    9   16:new             #21  <Class StringBuilder>
    
//
   10   19:dup             
    
//
   11   20:aload_1         
    
//
   12   21:invokestatic    #23  <Method String String.valueOf(Object)>
    
//
   13   24:invokespecial   #29  <Method void StringBuilder(String)>
    
//
   14   27:aload_2         
    
//
   15   28:sipush          1000
    
//
   16   31:invokevirtual   #32  <Method int Random.nextInt(int)>
    
//
   17   34:invokevirtual   #36  <Method StringBuilder StringBuilder.append(int)>
    
//
   18   37:ldc1            #40  <String " ">
    
//
   19   39:invokevirtual   #42  <Method StringBuilder StringBuilder.append(String)>
    
//
   20   42:invokevirtual   #45  <Method String StringBuilder.toString()>
    
//
   21   45:astore_1        

    
//
   22   46:iinc            3  1
    
//
   23   49:iload_3         
    
//
   24   50:bipush          10
    
//   25   52:icmplt          16

        System.out.println(s);
    
//
   26   55:getstatic       #49  <Field PrintStream System.out>
    
//
   27   58:aload_1         
    
//
   28   59:invokevirtual   #55  <Method void PrintStream.println(String)>
    
//   29   62:return          

    }

}



大家可以看到,虽然编译器将"+"转换成了StringBuilder,但创建StringBuilder对象的位置却在for语句内部。这就意味着每执行一次循环,就会创建一个StringBuilder对象(对于本例来说,是创建了10个StringBuilder对象),虽然Java有垃圾回收器,但这个回收器的工作时间是不定的。如果不断产生这样的垃圾,那么仍然会占用大量的资源。解决这个问题的方法就是在程序中直接使用StringBuilder来连接字符串,代码如下:

package string;

import java.util.*
;

public class
 TestStringBuilder
{
    
public static void
 main(String[] args)
    
{
        String s 
= ""
;
        Random rand 
= new
 Random();
        StringBuilder result 
= new
 StringBuilder();
        
for (int i = 0; i < 10; i++
)
        
{
            result.append(rand.nextInt(
1000
));
            result.append(
" "
);
        }

        System.out.println(result.toString());
    }

}


上面代码反编译后的结果如下:
package string;

import
 java.io.PrintStream;
import
 java.util.Random;

public class
 TestStringBuilder
{

    
public
 TestStringBuilder()
    
{
    
//
    0    0:aload_0         
    
//
    1    1:invokespecial   #8   <Method void Object()>
    
//    2    4:return          

    }


    
public static void main(String args[])
    
{
        String s 
= ""
;
    
//
    0    0:ldc1            #16  <String "">
    
//    1    2:astore_1        

        Random rand = new Random();
    
//
    2    3:new             #18  <Class Random>
    
//
    3    6:dup             
    
//
    4    7:invokespecial   #20  <Method void Random()>
    
//    5   10:astore_2        

        StringBuilder result = new StringBuilder();
    
//
    6   11:new             #21  <Class StringBuilder>
    
//
    7   14:dup             
    
//
    8   15:invokespecial   #23  <Method void StringBuilder()>
    
//    9   18:astore_3        

        for(int i = 0; i < 10; i++)
    
//
*  10   19:iconst_0        
    
//
*  11   20:istore          4
    
//*  12   22:goto            47

        {
            result.append(rand.nextInt(
1000
));
    
//
   13   25:aload_3         
    
//
   14   26:aload_2         
    
//
   15   27:sipush          1000
    
//
   16   30:invokevirtual   #24  <Method int Random.nextInt(int)>
    
//
   17   33:invokevirtual   #28  <Method StringBuilder StringBuilder.append(int)>
    
//   18   36:pop             

            result.append(" ");
    
//
   19   37:aload_3         
    
//
   20   38:ldc1            #32  <String " ">
    
//
   21   40:invokevirtual   #34  <Method StringBuilder StringBuilder.append(String)>
    
//   22   43:pop             

        }


    
//   23   44:iinc            4  1
    
//
   24   47:iload           4
    
//
   25   49:bipush          10
    
//   26   51:icmplt          25

        System.out.println(result.toString());
    
//
   27   54:getstatic       #37  <Field PrintStream System.out>
    
//
   28   57:aload_3         
    
//
   29   58:invokevirtual   #43  <Method String StringBuilder.toString()>
    
//
   30   61:invokevirtual   #47  <Method void PrintStream.println(String)>
    
//   31   64:return          

    }

}



从上面的反编译结果可以看出,创建StringBuilder的代码被放在了for语句外。虽然这样处理在源程序中看起来复杂,但却换来了更高的效率,同时消耗的资源也更少了。
在使用StringBuilder时要注意,尽量不要"+"和StringBuilder混着用,否则会创建更多的StringBuilder对象,如在TestStringBuilder.java中的

for (int i = 0; i < 10; i++)
    
{
        result.append(rand.nextInt(
1000
));
        result.append(
" "
);
    }


改成如下形式:

for (int i = 0; i < 10; i++)
{
     result.append(rand.nextInt(
1000) + " "
);
}


则反编译后的结果如下:

... ...
   
for(int i = 0; i < 10; i++
)
  
//
*  10   19:iconst_0        
  
//
*  11   20:istore          4
  
//*  12   22:goto            65

   {
    result.append((
new StringBuilder(String.valueOf(rand.nextInt(1000)))).append(" "
).toString());
  
//
   13   25:aload_3         
  
//
   14   26:new             #21  <Class StringBuilder>
  
//   15   29:dup             

  ... ...

从上面的代码可以看出,Java编译器将"+"编译成了StringBuilder,这样for语句每循环一次,又创建了一个StringBuilder对象。
    如果将上面的代码在JDK1.4下编译,必须将StringBuilder改为StringBuffer,而JDK1.4将"+"转换为StringBuffer(因为JDK1.4并没有提供StringBuilder类)。StringBuffer和StringBuilder的功能基本一样,只是StringBuffer是线程安全的,而StringBuilder不是线程安全的。因此,StringBuilder的效率会更高。
 
 下面的代码是测试"+"和StringBuilder效率的代码:

 

public class thinking
{
    
private static void usePlus(int
 n)
    
{
        
long t =
 System.currentTimeMillis();
        String s 
= ""
;
        
for (int i = 0; i < n; i++
)
            s 
= s +
 i;
        System.out.println(s);
        System.out.println(
"+:"

                
+ String.valueOf(System.currentTimeMillis() - t));
    }

    
private static void useStringBuilder(int n)
    
{
        
long t =
 System.currentTimeMillis();
        StringBuilder str 
= new
 StringBuilder();
        
for (int i = 0; i < n; i++
)
            str.append(i);
        System.out.println(str.toString());
        System.out.println(
"StringBuilder:"

                
+ String.valueOf(System.currentTimeMillis() - t));
    }

    
public static void main(String[] args)
    
{
        useStringBuilder(
2000
);
        usePlus(
2000
);
    }

}


输出结果

01234567891011121314151617181920212 ... ...
StringBuilder:30
01234567891011121314151617181920212 ... ...
+:151

从上面的输出结果可以看出,使用StringBuilder的效率明显要比"+"高

 
注:此文可任意转载,但要注明作者和出处
无人机蜂群作战设计技术详解 构建防御网络,拦截敌方无人机或导弹;无人机蜂群作战设计技术是一种创新的军事应用概念,它基于生物仿生学原理,通过先进的通信技术、自主导航与决策算法,将大量小型、低成本、功能各异的无人机组织成一个高度协同的群体,以执行复杂多样的军事任务。无人机蜂群作战的概念源于自然界中蜜蜂、蚂蚁等生物群体的行为模式,这些生物群体通过简单的个体间的信息交互和分工协作,能够完成远远超出单一个体能力的复杂任务。其中,无人机群体是执行任务的主体,指挥控制系统负责任务分配和决策,通信数据链则保障无人机群体与指挥控制系统之间的信息交换。 阅读详情

相关推荐

操作不能完成 (错误 0x00000709) 共享打印机无法连接解决办法

环境:windows Server 2012 + Win10 客户端 问题:使用计算机名和IP地址可以正常连接打印机,但是使用另外的A记录或CN记录无法连接,报此错误 原因:这是打印服务DNS解析的问题 故障补充:假设你的服务器电脑名称叫print01,但是你又建了一条A记录或者CNname 叫PR01,就会发现使用额外的A记录或CN记录就无法连接 故障截图: 操作不能完成 (错误...

瑞哥的博客 3万+

String拼接也有用加号更好的时候

做String拼接时用StringBuilder(或StringBuffer)好还是直接用+号性能好?一般来说是前者,不过也有用加号略好的时候。首先我一直认为用+号有很好的可读性,而且当String拼接在一个等式时,即形如String s = “abc” + s2 + s3jdk的实现原理也是转换为一个StringBuilder并一直append,效率也是差不太多的,所以我是比较喜欢在无循环或条件...

weixin_30622181的博客 647

一种车内UWB圆极化天线的理论推导及具体实现

本文详细描述了一款工作于UWB channel 9也即中心频率为7987.2MHz,带宽为499.2MHz的圆极化天线。首先是理论推导圆极化天线的物理尺寸参数,分析物理尺寸参数对天线性能指标的影响。然后分析圆极化天线在汽车驾驶室这种狭窄空间应用中带来的优势,也即可以最大化的极化损失多径,提高主径接收信号的信噪比。

weixin_44555637的博客 2965

什么情况下用“+”运算符进行字符串连接比调用StringBuffer/StringBuilder 对象的append方法连接字符串性能更好?

对于这个问题,分2种情况。 1.不涉及对象拼接,只有常量字符串的拼接 。如下: String s = “ab”+“cd”,JVM会直接处理成String s = “abcd”; 2.涉及到对象拼接。如下: String s = “ab”; String ss = s +“cd”; 细分为2种情况, ①:没有for循环。“+”与StringBuilder效果一样 ②:对于for循环。StringBuilber的对象写在循环外,减少对象的创建,性能比“+”好。具体如下: StringBuilber的对象写在循环

qq_41570705的博客 1006

在Mac下配置用VSCode编写C/C++程序的环境

前言    最近需要编写一些C/C++程序,由于体量都不是很大所以想要追求一个轻量化的编辑和编译环境,于是想起了在Dock栏吃灰的VSCode。通过查找资料,包括VSCode的官方文档,最终配置实现了Mac下基于VSCode的C/C++编辑环境搭建。 正文    在配置环境之前先检查一下机器上都安装了什么C++编译器,通过以下两条命令可以查看是否安装了g++/clang编译器,本人两种编...

Kalikali的专栏 5万+

Abaqus 单元与全局刚度矩阵导出实战指南:从INP修改到结果解析

本文提供了Abaqus中导出单元刚度矩阵和全局刚度矩阵的完整实战指南。通过详细步骤讲解INP文件修改、关键指令插入及结果文件解析,帮助工程师、研究人员和二次开发者深入理解有限元软件内核,实现理论验证、二次开发与深度问题调试。

k8s6orchestrator的博客 898

java学习笔记--面试题

面试题 Intern()方法会把首次遇到的字符串实例复制到永久代中,返回的是永久代中这个字符串实例的引用。在jdk1.7中intern()实现不会再复制实例,只是在常量池中记录首次出现的实例。 数组没有length()方法。有length属性。String 有length()方法; 在最外层循环前添加一个标记A 使用break A;可以跳出多重循环。 instanceof可以检查参数是否为正确类...

qq_41024497的博客 331

【人工智能】《Deep Dive into LLMs like ChatGPT 》—— Andrej Karpathy 第三阶段:强化学习(Reinforcement Learning, RL)

摘要:强化学习(RL)阶段通过让模型自主生成并验证答案,突破SFT阶段的模仿局限,使其在数学、代码等领域形成独特的推理路径。RL流程包括批量生成解答、自动批改筛选正确路径,并采用PPO/GRPO算法优化模型。模型会自发涌现自我检查、回滚等策略,显著提升正确率(如AIME竞赛准确率从15%升至56%)。与SFT模型相比,RL模型具备主动链式思维、验算能力,响应时间更长但效果更优,形成真正的“思考模型”。三阶段对比显示,RL通过可验证题的对错奖励机制,赋予模型超越人类范式的推理能力。

奶爸的编程之路,也就一周冷个三天 149

java 字符串拼接为什么要用 StringBuilder 而不直接用 String 相加连接

经常在网上看到或者在周围听到有人说字符串拼接不要直接用 String 相加, StringBuilder 的效率要比 String 直接相加拼接要高。还有人常说, StringBuffer 是同步的(线程安全的), StringBuilder 不是线程安全的,同步带来了性能消耗,那么 String 、 StringBuilder 、 StringBuffer 这三者的效率到底有多大的差距呢?

1万+

基于Python的房地产评估数据抓取与分析 —— 房价走势与市场报告

在房地产行业中,了解和分析房产价格的变化趋势、各个地区的房价差异以及市场评价报告,可以帮助投资者、购房者以及政策制定者做出更加明智的决策。本文介绍了如何使用Python爬虫技术抓取房地产平台上的房产评估报告、价格走势等数据,并对抓取的数据进行分析。通过这些技术,您可以自动化抓取房地产平台的数据,分析房价走势,获取市场报告,为房地产投资决策提供数据支持。假设我们要从链家网抓取某个房产的价格、房产描述以及历史成交价格,首先需要获取目标房产页面的URL,并发送HTTP请求。伪装为常见浏览器,避免被识别为爬虫。

2201_76125261的博客 847

038、OIS 光学防抖原理与调试:陀螺仪数据融合、Lens Shift OIS 的闭环控制

本文分享了OIS光学防抖系统的调试经验和关键技术要点。作者通过一个"呼吸感"Bug案例,揭示了陀螺仪数据融合和闭环控制的重要性。系统介绍了OIS的三个关键层次:传感器层(陀螺仪特性)、控制层(复合算法)和执行层(闭环控制)。重点讲解了陀螺仪数据融合的互补滤波实现、Lens Shift闭环控制的PID优化策略(包括积分抗饱和和微分滤波),以及前馈补偿的应用。最后总结了调试中的关键问题:数据同步、霍尔校准、温度补偿和性能评估方法,并给出实用建议:平衡算法复杂度与性能、预留带宽余量、重视产线校准等。文章强调OIS

sundong_81的博客 263

华为:什么情况下用“+”运算符进行字符串连接比调用 StringBuffer/StringBuilder 对象的 append 方法连接字符串性能更好?

字符串是 Java 程序中最常用的数据结构之一。在 Java 中 String 类已经重载了"+"。但这样做真的好吗?当然,这个问题不能简单地回答 yes or no。要根据具体情况来定。在 Java 中提供了一个StringBuilder 类(这个类只在 J2SE5 及以上版本提供,以前的版本使用 StringBuffer 类),这个类也可以起到"+"的作用。那么我们应该用哪个呢?上面的代码将会输出正确的结果。从表面上看,对字符串和整型使用"+"号并没有什么区别,但事实真的如此吗?

2401_83384536的博客 794

WOFOST作物模型(7):6.0.6版本的PCSE使用(多层水分平衡和SNOMIN碳氮模型的集成)

wofost81文件结构如上,其中所需的参数可从github上获取然后input下有两个需要调用的功能函数py文件,需要拖到自己的运行py文件同级目录下在使用土壤模块SNOMIN进行作物生长模型模拟时,需要为土壤剖面的不同层次提供多种输入变量。这些变量通常不随年份变化,因此会统一在土壤文件中定义。本节将说明如何将这些输入变量整合到一个字典中,进而生成SNOMIN能够读取的土壤文件。

所有专家都曾始于新手 638

在Java中连接字符串时是使用+号还是使用StringBuilder StringBuffer 加号

字符串是Java程序中最常用的一种数据结构之一。在Java中的String类已经重载的"+"。也就是说,字符串可以直接使用"+"进行连接,如下面代码所示: String s = "abc" + "ddd"; 但这样做真的好吗?当然,这个问题不能简单地回答yes or no。要根据具体情况来定。在Java中提供了一个StringBuilder类(这个类只在J2SE5及以上版本

qq897958555的博客 481

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

浅谈Java中连接字符串时使用"+"号和使用StringBuilder类的区别

主页君在留言板中看到有Javaer提出一个问题,就是Java里在连接字符串时,使用"+"号连接还是使用StringBuilder类(这个类只在J2SE5及以上版本提供,以前的版本使用StringBuffer类)连接。   为了解答这位Javaer的疑惑,可能也是许多人的疑惑,特此撰文来解答这个问题,同时也附上另外一个困扰很多Javaer的问题,就是"+"号和StringBuilder类连接字

1653

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

Java中连接字符串时使用+号与使用StringBuilder的区别

字符串是Java程序中最常用的一种数据结构之一。在Java中的String类已经重载的”+”。也就是说,字符串可以直接使用”+”进行连接,如下面代码所示: String s = "abc" + "ddd";   但这样做真的好吗?当然,这个问题不能简单地回答yes orno。要根据具体情况来定。   在Java中提供了一个StringBuilder类(这个类只在J2SE5及以上版本提供,以前

Song's Blog 2071

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

上一篇: java面试笔试题大汇总
下一篇: 如何防止重载toString方法时产生递归调用
atomic_age
博客等级 码龄21年 14粉丝 48原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值