面试官:“小伙子,在日常的写代码过程中,使用过String,StringBuilder和StringBuffer没?”

我:“用过的呀!”

面试官:“那你就来聊一聊,他们之间有什么区别,不同场景下如何选择吧”

我:“好嘞!”

在Java的开发过程中,使用频率最高的就是String字符串,但由于在字符串存储和拼接的过程中,涉及到很多场景需要因地制宜的选用StringBuider与StringBuffer。

我们先来聊一聊String,由源码引入话题:

Java8中的String源码

public final class String implements java.io.Serializable, Comparable<String>, CharSequence {
private final char value[];
//...
}

我们从源码中可以总结出如下几点内容:

  1. String类被final关键字修饰,意味着它不可被继承;
  2. String的底层采用了final修饰的char数组,意味着它的不可变性;
  3. 实现了Serializable接口意味着它支持序列化;
  4. 实现了Comparable接口,意味着字符串的比较可以采用compareTo()方法,而不是==号,并且Sring类内部也重写了Object的equals()方法用来比较字符串相等。

Java9以后String的底层数据由char类型改为了byte类型,看源码:

public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
@Stable
private final byte[] value;
private final byte coder;
private int hash;
}

这样做的目的是为了节省字符串占用的内存空间,在大字符串处理中提升效率,同时也降低了垃圾回收的次数,提升性能。

面试官:“String类设置为不可变对象的话,岂不是每次创建或者字符串拼接的时候都会创建对象,增加开销?那为什么还要用final修饰呢?”

我:“嗯~这个问题非常好呀,我理解的是两个原因”

1、String 类是最常用的类之一,为了效率,禁止被继承和重写
2、为了安全。String 类中有很多调用底层的本地方法,调用了操作系统的API,
如果方法可以重写,可能被植入恶意代码,破坏程序。其实Java 的安全性在这里就有一定的体现啦。

基于以上String的特点,Java官方自然也知道它的弊端,所以为了全场景的最优方案适配,便产生了StringBuilder和StringBuffer这两个String的近亲字符串处理类,他们都实现了CharSequence 接口。

StringBuilder 与 StringBuffer 都继承自 AbstractStringBuilder 类,在 AbstractStringBuilder 中也是使用字符数组保存字符串,不过没有使用 final 和 private 关键字修饰,所以可以解决在字符串拼接时的性能问题,最关键的是这个 AbstractStringBuilder 类还提供了很多修改字符串的方法,比如 append 方法。

源码:

abstract class AbstractStringBuilder implements Appendable, CharSequence {
char[] value;
public AbstractStringBuilder append(String str) {
if (str == null)
return appendNull();
int len = str.length();
ensureCapacityInternal(count + len);
str.getChars(0, len, value, count);
count += len;
return this;
}
//...
}

StringBuilder源码

public final class StringBuilder extends AbstractStringBuilder
implements java.io.Serializable, CharSequence
{
// ... public StringBuilder append(String str) {
super.append(str);
return this;
} public String toString() {
// Create a copy, don't share the array
return new String(value, 0, count);
} // ...
}

StringBuilder替代String的字符串拼接案例

Java 是一门解释型的编程语言,所以当编译器遇到 + 号这个操作符的时候,会将

new String("Hello") + new String("World")

解释为

new StringBuilder().append("Hello").append("World").toString();

并且在循环字符串拼接的时候,String的“+”拼接方式,会在循环内部多次创建StringBuilder对象,白白浪费了资源,如:

String[] arr = {"he", "llo", "world"};
String s = "";
for (int i = 0; i < arr.length; i++) {
s += arr[i];
}
System.out.println(s);

这一段代码完全就可以直接使用StringBuilder调用append实现方式来替代:

String[] arr = {"he", "llo", "world"};
StringBuilder s = new StringBuilder();
for (String value : arr) {
s.append(value);
}
System.out.println(s);

StringBuffer源码

public final class StringBuffer extends AbstractStringBuilder implements Serializable, CharSequence {

    public StringBuffer() {
super(16);
} public synchronized StringBuffer append(String str) {
super.append(str);
return this;
} public synchronized String toString() {
return new String(value, 0, count);
} // 其他方法
}

从它的源码我们可以看出,内部的实现与StringBuilder相差无机,无非是在方法的前面加了synchronized 关键字进行了同步,以确保在多线程场景下的线程安全,但在大部分的非多线程场景下,由于同步锁的存在会导致执行效率过低,并且即便在多线程情况下,依旧可以通过ThreadLocal搭配StringBuilder的方式来安全的修改字符串,所以,实际开发中,StringBuilder 的使用频率也是远高于 StringBuffer,甚至可以这么说,StringBuilder 完全取代了 StringBuffer。

三者异同点总结

相同点:
1、都可以储存和操作字符串
2、都使用 final 修饰,不能被继承
3、提供的 API 相似
异同点:
1、String 是只读字符串,String 对象内容是不能被改变的
2、StringBuffer 和 StringBuilder 的字符串对象可以对字符串内容进行修改,在修改后的内存地址不会发生改变
3、StringBuilder 线程不安全;StringBuffer 线程安全

面试官:请聊一聊String、StringBuilder、StringBuffer三者的区别的更多相关文章

  1. java中String StringBuilder StringBuffer比较和效率(性能)测试

    string stringbuilder stringbuffer三者的区别 从JDK源码看,String.StringBuilder.StringBuffer都是存放在char[] 数组字符串. 简 ...

  2. Java中的String,StringBuilder,StringBuffer三者的区别?

    package com.aaa.zxf.ajax.test; /** * 弄清楚 string stringBuilder StringBuffer 三者之间的关系? * * * 一. 三者都是用来对 ...

  3. String,StringBuilder,StringBuffer三者的区别

    参考   String,StringBuilder,StringBuffer三者的区别 这三个类之间的区别主要是在两个方面,即运行速度和线程安全这两方面. 1.运行速度 首先说运行速度,或者说是执行速 ...

  4. 33-Java中的String,StringBuilder,StringBuffer三者的区别

    转载自:https://www.cnblogs.com/su-feng/p/6659064.html StringBuilder 详解 (String系列之2) Java中的String,String ...

  5. 深入源码剖析String,StringBuilder,StringBuffer

    [String,StringBuffer,StringBulider] 深入源码剖析String,StringBuilder,StringBuffer [作者:高瑞林] [博客地址]http://ww ...

  6. JDK源码分析系列---String,StringBuilder,StringBuffer

    JDK源码分析系列---String,StringBuilder,StringBuffer 1.String public final class String implements java.io. ...

  7. String, StringBuilder, StringBuffer问题

    1. 区别 String为字符串常量,而StringBuilder和StringBuffer都是字符串变量,其中StringBuilder线程非安全,StringBuffer线程安全. 每次对 Str ...

  8. String StringBuilder StringBuffer区别

    String StringBuilder StringBuffer String类是final类,不可以被继承,且它的成员方法也是final方法,当一个字符串对象进行操作操作时,任何的改变不会影响到这 ...

  9. difference among String,StringBuilder,StringBuffer

    difference among String,StringBuilder,StringBuffer String常用构造函数 String(byte[] bytes) String(byte[] b ...

  10. Java—String,StringBuffer,StringBuilde区别和操作

    Java语言有关字符串的类有三种 java.lang.String:一般作为简单字符串类型 java.lang.StringBuffer:字符串缓冲区 java.lang.StringBuider:字 ...

随机推荐

  1. python之递归(斐波那契数列)与迭代

    对于较大的计算来说,迭代不如递归计算速度快,并且可以说非常慢 但是迭代对于较小的运算又比递归巧妙 # 迭代方法 def slowsnail(x): am = [1, 1] if x < 0: p ...

  2. UNI-APP之微信小程序转H5

    开始 最近有个需求,需要将微信小程序中一些页面和功能改成h5,这次功能开发的时间有点紧,而且重新写一套有点来不及.考虑到微信小程序与uni-app有着一些共通之处,所以打算直接转成uni-app.un ...

  3. Modbus 转PROFINET 网关 TS-180在级联通讯中的应用

    一.硬件连接 TS-180 具有冗余网口功能,用户可以通过级联方式连接来进行通讯,其他资料可参考说明书.将西门子 S7-300 PLC 通过网线与5台 TS-180 串联,用户可以选择下列两种连接方式 ...

  4. EMCC13.5+Oracle19.13+Redhat8 In Silent Mode

    问题描述:使用静默的方式来安装emcc13.5+Oracle19.13,准备好19c的oracle环境,一开始用21c的库+emcc13.5的安装检查一直过不去,但是19c是没有问题的,具体问题会在下 ...

  5. Go语言函数详解

    函数 (1)函数的定义 函数使用func进行定义 函数是基本的代码块,用于执行一个任务 Go语言至少有一个main函数 函数声明告诉了编译器函数的名称,返回类型和参数 //1.无参数无返回值函数的定义 ...

  6. 2分钟,快速认识什么是SQL

    结构化查询语言,简称SQL,它是与关系数据库管理系统通信的黄金标准语言.今天就来一起快速认识一下什么是SQL,您可以通过以下的文字内容学习,也可以通过文末的视频学习,希望本文对您有所帮助. 您可能听说 ...

  7. Web前端工程的装机必备软件

    前言 最近作者的电脑 C 盘变红了,这让我很难受(有点小强迫症),所以准备重新安装下系统,顺便把 C 盘扩大点. 注意: 操作系统是 windows 11 23H2. 所有的命令行都是使用 Windo ...

  8. 吉特日化MES配料工艺参数标准版-第二版

    作者:情缘 出处:http://www.cnblogs.com/qingyuan/ 关于作者:从事仓库,生产软件方面的开发,在项目管理以及企业经营方面寻求发展之路 版权声明:本文版权归作者和博客园共有 ...

  9. 8 HTTP 的请求方法

    目录 标准请求方法 GET/HEAD GET 方法 HEAD方法 POST/PUT POST PUT 非常用方法 DELETE 方法 CONNECT 方法 OPTIONS 方法 TRACE 方法 拓展 ...

  10. bash shell笔记整理——date命令

    date命令初步了解 简单来说date的主要作用大多数用于以给定的格式来显示时间. 在后期我们写一些脚本当中也会使用到,比如说按照日期来给文件备份打包等. 下面我们来看看帮助信息: [root@ngi ...