String、StringBuilder、StringBuffer的区别

它们之间的区别:

在我们学习String类的时候,也会学习到StringBuilder和StringBuffer,但是他们之间有什么区别呢? 当然他们在具体的代码实现上、内存分配上以及效率上都有着不同(我这里以JDK8为例);

一、代码实现
String

public final class Stringimplements java.io.Serializable, Comparable<String>, CharSequence {/** The value is used for character storage. */private final char value[];/** Cache the hash code for the string */private int hash; // Default to 0/** use serialVersionUID from JDK 1.0.2 for interoperability */private static final long serialVersionUID = -6849794470754667710L;/*** Class String is special cased within the Serialization Stream Protocol.** A String instance is written into an ObjectOutputStream according to* <a href="{@docRoot}/../platform/serialization/spec/output.html">* Object Serialization Specification, Section 6.2, "Stream Elements"</a>*/private static final ObjectStreamField[] serialPersistentFields =new ObjectStreamField[0];/*** Initializes a newly created {@code String} object so that it represents* an empty character sequence.  Note that use of this constructor is* unnecessary since Strings are immutable.*/public String() {this.value = "".value;}/*** Initializes a newly created {@code String} object so that it represents* the same sequence of characters as the argument; in other words, the* newly created string is a copy of the argument string. Unless an* explicit copy of {@code original} is needed, use of this constructor is* unnecessary since Strings are immutable.** @param  original*         A {@code String}*/public String(String original) {this.value = original.value;this.hash = original.hash;}

从这里我们可以看出,String的底层结构是private final char value[];所以String的值是不可变的,并且实现了Comparable接口,所以是支持比较的。

StringBuilder

public final class StringBuilderextends AbstractStringBuilderimplements java.io.Serializable, CharSequence
{/** use serialVersionUID for interoperability */static final long serialVersionUID = 4383685877147921099L;/*** Constructs a string builder with no characters in it and an* initial capacity of 16 characters.*/public StringBuilder() {super(16);}/*** Constructs a string builder with no characters in it and an* initial capacity specified by the {@code capacity} argument.** @param      capacity  the initial capacity.* @throws     NegativeArraySizeException  if the {@code capacity}*               argument is less than {@code 0}.*/public StringBuilder(int capacity) {super(capacity);}/*** Constructs a string builder initialized to the contents of the* specified string. The initial capacity of the string builder is* {@code 16} plus the length of the string argument.** @param   str   the initial contents of the buffer.*/public StringBuilder(String str) {super(str.length() + 16);append(str);}/*** Constructs a string builder that contains the same characters* as the specified {@code CharSequence}. The initial capacity of* the string builder is {@code 16} plus the length of the* {@code CharSequence} argument.** @param      seq   the sequence to copy.*/public StringBuilder(CharSequence seq) {this(seq.length() + 16);append(seq);}@Overridepublic StringBuilder append(Object obj) {return append(String.valueOf(obj));}@Overridepublic StringBuilder append(String str) {super.append(str);return this;}

从这里我们可以看出StringBuilder有一个抽象父类,他是没有实现Comparable接口,明显不支持比较。我们看到AbstractStringBuilder类中,value是可变的,并不像String有final修饰

AbstractStringBuilder

abstract class AbstractStringBuilder implements Appendable, CharSequence {/*** The value is used for character storage.*/char[] value;/*** The count is the number of characters used.*/int count;/*** This no-arg constructor is necessary for serialization of subclasses.*/AbstractStringBuilder() {}

StringBuffer

public final class StringBufferextends AbstractStringBuilderimplements java.io.Serializable, CharSequence
{/*** A cache of the last value returned by toString. Cleared* whenever the StringBuffer is modified.*/private transient char[] toStringCache;/** use serialVersionUID from JDK 1.0.2 for interoperability */static final long serialVersionUID = 3388685877147921107L;/*** Constructs a string buffer with no characters in it and an* initial capacity of 16 characters.*/public StringBuffer() {super(16);}/*** Constructs a string buffer with no characters in it and* the specified initial capacity.** @param      capacity  the initial capacity.* @exception  NegativeArraySizeException  if the {@code capacity}*               argument is less than {@code 0}.*/public StringBuffer(int capacity) {super(capacity);}/*** Constructs a string buffer initialized to the contents of the* specified string. The initial capacity of the string buffer is* {@code 16} plus the length of the string argument.** @param   str   the initial contents of the buffer.*/public StringBuffer(String str) {super(str.length() + 16);append(str);}/*** Constructs a string buffer that contains the same characters* as the specified {@code CharSequence}. The initial capacity of* the string buffer is {@code 16} plus the length of the* {@code CharSequence} argument.* <p>* If the length of the specified {@code CharSequence} is* less than or equal to zero, then an empty buffer of capacity* {@code 16} is returned.** @param      seq   the sequence to copy.* @since 1.5*/public StringBuffer(CharSequence seq) {this(seq.length() + 16);append(seq);}@Overridepublic synchronized int length() {return count;}@Overridepublic synchronized int capacity() {return value.length;}

而StringBuffer同样是继承一个抽象父类AbstractStringBuilder,它的底层结构同样是可变的char[] value数组也没有实现Comparable接口。

StringBuffer和StringBuilder虽然结构是一样的,但还是有不同点。StringBuffer多了几样东西。
如:
1、toStringCache它是用于执行toString()方法时,把值保存到变量中,下次继续执行toString()方法时,可以直接从变量中取出来。变量是transient 修饰的,代表着不可序列化。
2、还有一个本质上的区别,StringBuffer的方法是synchronized修饰的,代表着是线程安全的。

二、性能效率
String

//        StirngString str = "";long oldTime = System.currentTimeMillis();for (int i = 0; i < 100000; i++) {str += "a";}System.out.printf("耗时:%d ms",(System.currentTimeMillis() - oldTime));

我这里使用for循环,每循环一次,都往str中拼接字符串"a",总共循环10万次。执行时间达到了平均11秒,太可怕了,效率实在太慢太慢了。

StringBuilder

//      StringBuilderStringBuilder str = new StringBuilder("");long oldTime = System.currentTimeMillis();for (int i = 0; i < 10000000; i++) {str.append("a");}System.out.printf("耗时:%d ms",(System.currentTimeMillis() - oldTime));

我这里使用StringBuilder的append方法进行拼接字符串,拼接1000万次,平均执行时间只需279毫秒,这里对比String可以看出,在大量拼接字符串的时候,String的劣势很明显。
当然StringBuilder虽然够快,但也有他的劣势,在多线程的环境下是线程不安全的。

StringBuffer

//        StringBufferStringBuffer str = new StringBuffer("");long oldTime = System.currentTimeMillis();for (int i = 0; i < 10000000; i++) {str.append("a");}System.out.printf("耗时:%d ms",(System.currentTimeMillis() - oldTime));

这里同样使用StringBuffer拼接字符串,同样1000万次,耗时平均550毫秒。虽然它没有StringBuilder快,但是它可以保证线程安全,我们前面讲过StringBuffer的方法是synchronized修饰的。当然线程安全就代表着它性能效率会被降低了,因为我们的线程需要去竞争锁,竞争到锁的线程才可以执行,虽然有偏向锁,性能难免会被降低。

三、内存分配

JVM内存区域划分如下(自画,如果有觉得错的地方,可以私信我修正哈)

在这里插入图片描述

String

String str = “a” + “b” + “c”; //我们以这段代码为例,我们来看看内存中是如何分配的

在这里插入图片描述
【总所周知,字符串常量池在JDK7中从方法区搬到了堆中!】
(字面量:字符串常量池中带"“双引号的字,如"a”、“b”、"c"都是字面量)
我们可以看到,在使用String进行拼接不同字符串的时候,每次拼接相连,都会在常量池中创建相应的字面量。这是因为String的value是final修饰的,并不能直接修改,所以会一直创建新的对象,并重新进行赋值。

在JDK9中,String底层是“byte[]”,并不是“char[]”了,这样做的目的就是可以通过编码的方式来存储,可以减少内存的占用和提高性能,我测试过性能快了不止一倍。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/557568.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2016年 java_2016年java考试试题及答案

2016年java考试试题及答案简答应用题1.下面程序运行后&#xff0c;可以使用上下左右键移动组件。 补充下画线部分的代码。import java.awt.*;import java.awt.event.*;public class E6 extends Frame implements keyListener{TextField b1;int x,y;E6(){setLayout (new FlowLay…

【Java深入理解】String str = “a“ + “b“ + “c“到底创建了几个对象?

String str “a” “b” “c"到底创建了几个对象&#xff1f;这是我们在讨论中最经常遇到的一个问题同时也是面试题。我们都知道在Java中从”.java"文件编译成".class"文件的过程&#xff0c;会有一个优化器去优化我们的代码。这个问题需要分成三种情况…

Linux中如何查看某个端口是否被占用

Linux中如何查看某个端口是否被占用 1.netstat -anp |grep 端口号 如下&#xff0c;我以3306为例&#xff0c;netstat -anp |grep 3306&#xff08;此处备注下&#xff0c;我是以普通用户操作&#xff0c;故加上了sudo&#xff0c;如果是以root用户操作&#xff0c;不用加sudo…

java 压缩jar 仓库,java服务安装(一):使用java service wrapper及maven打zip包

tags&#xff1a; java jsw maven zip1、概述使用java开发程序&#xff0c;在windows平台下&#xff0c;一般有web应用&#xff0c;后台服务应用&#xff0c;桌面应用&#xff1a;web应用多数打成war包在web容器(如tomcat,jetty等)中运行桌面应用一般打成jar包或exe文件运行后台…

如何处理代码冲突

如何处理代码冲突 冲突合并一般是因为自己的本地做的提交和服务器上的提交有差异&#xff0c;并且这些差异中的文件改动&#xff0c;Git不能自动合并&#xff0c;那么就需要用户手动进行合并 如我这边执行git pull origin master 如果Git能够自动合并&#xff0c;那么过程看…

如何理解NIO

文章目录1.什么是NIO&#xff1f;2.为什么用NIO&#xff0c;传统IO有什么缺陷&#xff1f;3.NIO和IO的区别4.怎么理解NIO是面向块的、非阻塞的5.NIO是怎么实现的&#xff1f;1.什么是NIO&#xff1f; java.nio全称java non-blocking IO&#xff08;实际上是 new io&#xff09…

sublime php快捷键,分享Sublime Text 3快捷键精华版!

下面由sublime教程栏目给大家介绍Sublime Text 3 快捷键精华版&#xff0c;希望对需要的朋友有所帮助&#xff01;CtrlShiftP&#xff1a;打开命令面板CtrlP&#xff1a;搜索项目中的文件CtrlG&#xff1a;跳转到第几行CtrlW&#xff1a;关闭当前打开文件CtrlShiftW&#xff1a…

JDBC中使用preparedStatement防止SQL注入

一、SQL注入 SQL注入是一种比较常见的网路攻击方式&#xff0c;一些恶意人员在需要用户输入的地方&#xff0c;恶意输入SQL语句的片段&#xff0c;通过SQL语句&#xff0c;实现无账号登录&#xff0c;甚至篡改数据库。 二、SQL注入实例 登录场景&#xff1a; 在一个登录界面…

Java预科篇1-学前

Java预科篇1-学前 1、markdown语法 Markdown是一种纯文本格式的标记语言。通过简单的标记语法&#xff0c;它可以使普通文本内容具有一定的格式。 优点&#xff1a; 因为是纯文本&#xff0c;所以只要支持Markdown的地方都能获得一样的编辑效果&#xff0c;可以让作者摆脱排…

Java预科篇2-环境搭建

Java预科篇2-环境搭建 1、Java历史 1995年 Java问世1996年 Java 1.01999年 Java 1.2发布&#xff08;JAVA SE\JAVA EE\JAVA ME&#xff09;… … …2004年 Tiger 发布(JAVA5.0)&#xff0c;Java 登录火星2011年 7月由Oracle正式发布Java7.02014年 3月19日&#xff0c;Oracle公…

php中如何配置环境变量,如何配置phpstorm环境变量如何配置phpstorm环境变量

大话西游6664版。根据你的系统平台下载相应的版本后&#xff0c;如果是压缩文件&#xff0c;先解压后双击运行&#xff0c;不是压缩文件&#xff0c;直接双击运行就可以了&#xff0c;运行后出现下面的界面&#xff0c;在下面界面上单击“Next”。跟所有的软件安装包一样&#…

Java基础篇1——变量与数据类型

Java基础篇1——变量与数据类型 1、标识符命名规则 标识符以由大小写字母、数字、下划线(_)和美元符号($)组成&#xff0c;但是不能以数字开头。大小写敏感不能与Java语言的关键字重名不能和Java类库的类名重名不能有空格、、#、、-、/ 等符号长度无限制应该使用有意义的名称…

Error running tomcat8 Address localhost:1099 is already in use 错误解决

错误情况&#xff1a; 在IDEA上运行web项目时报错&#xff1a;Error running &#xff08;项目名&#xff09; Address localhost:1099 is already in use 解决方法&#xff1a; 第一步&#xff1a;打开Windows运行&#xff0c;如下图 第二步&#xff1a;按下回车或点击确定…

matlab数据处理 书,matlab数据处理记录

最近在看一篇论文&#xff0c;觉得文章的数据处理效果十分的惊艳&#xff01;所以想着如何用matlab将类似的效果实现出来&#xff0c;但最近有一个任务&#xff0c;以后慢慢更新吧&#xff01;先挖一个坑&#xff01;1. 二维图形绘制二维坐标轴图像涉及的部分包含曲线的颜色、点…

MATLAB接收机位置解算,GPS-receiver GPS软件接收机代码 完整的捕获 解算定位 (可 8个通道) matlab 240万源代码下载- www.pudn.com...

文件名称: GPS-receiver下载 收藏√ [5 4 3 2 1 ]开发工具: matlab文件大小: 148 KB上传时间: 2015-07-02下载次数: 0提 供 者: 金亚强详细说明&#xff1a;GPS软件接收机代码 完整的捕获接受解算定位代码(可接受8个通道)-GPS software receiver codes文件列表(点击判断是…

oracle中$的用法,关于expdp 中query用法小结

今天看到群里有人问到关于在使用expdp导出数据中使用query参数报错的解决方法&#xff0c;自己也出于好奇心瞎折腾了一把&#xff0c;现记录如下1.第一次尝试的时候[oracleDB ~]$ expdp scott/scott tablesemp1 dumpfileemp1.dmp logfileemp1.log queryemp1:"where rownum…

oracle fnd file.log,OracleEBSWIP模块DebugLog收集方法

How to generate WIP debug log files in ONLINE cases? For 11.5.10 and above, the WIP debug log files will be created ifHow to generate WIP debug log files in ONLINE cases?For 11.5.10 and above, the WIP debug log files will be created if1. FND: Debug Log F…

linux怎么重装ssh服务器,Linux平台下安装SSH

什么是SSH&#xff1f;Secure Shell(缩写为SSH)&#xff0c;由IETF的网络工作小组(Network Working Group)所制定&#xff1b;SSH为一项创建在应用层和传输层基础上的安全协议&#xff0c;为计算机上的Shell(壳层)提供安全的传输和使用环境。传统的网络服务程序&#xff0c;如r…

Java核心类库篇4——集合

Java核心类库篇4——集合 1、集合的意义 记录单个数据内容时&#xff0c;则声明一个变量记录多个类型相同的数据内容时&#xff0c;声明一个一维数组记录多个类型不同的数据内容时&#xff0c;则创建一个对象记录多个类型相同的对象数据时&#xff0c;创建一个对象数组记录多…

计划任务文件 linux,Linux之任务计划

一、单次任务计划二、周期性任务计划一、单次任务计划命令&#xff1a;batch&#xff1a;系统空闲时自动执行&#xff0c;不常用at&#xff1a;可以使用相对时间、绝对时间或模糊时间&#xff0c;例如相对时间&#xff1a;at now3min&#xff0c;表示3分钟后执行绝对时间&#…