面试官:“小伙子,在日常的写代码过程中,使用过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. 【教程】cpp转python Nanobind 实践 加速轻量版 pythonbind11

    主要是尝试一下把c++这边的函数封装打包给python用,选择nanobind的原因是:1. 优化速度快,2. 生成二进制包小,不过pythonbind11是更为广泛知道的,nanobind也是pyt ...

  2. P1029 最大公约数和最小公倍数问题(普及−) 题解

    题目传送门 想要做这题,我们要先了解一下最大公约数. 最大公因数,也称最大公约数.最大公因子,指两个或多 个整数共有约数中最大的一个.a,b的最大公约数记为 (a,b),同样的,a,b,c的最大公约数 ...

  3. 基于Redis的简易延时队列

    基于Redis的简易延时队列 一.背景 在实际的业务场景中,经常会遇到需要延时处理的业务,比如订单超时未支付,需要取消订单,或者是用户注册后,需要在一段时间内激活账号,否则账号失效等等.这些业务场景都 ...

  4. kotlin+springboot入门级别教程,教你如何用kotlin和springboot搭建http

    先打开idea,或者用springboot官网.阿里云那边都行 然后点击新建项目,spring Initializr,我们都知道,springboot是支持kotlin的,除非你是kotlin1.3之 ...

  5. 吉特日化MES & 医药行业相关专业术语汇总

  6. 1.5万字 + 25张图盘点RocketMQ 11种消息类型,你知道几种?

    大家好,我是三友~~ 故事的开头是这样的 最近有个兄弟私信了我一张截图 我一看截图内容,好家伙,原来是我一年多前立的flag 倒不是我忘了这件事,我后来也的确写了一篇的关于RocketMQ运行的原理的 ...

  7. 《深入理解 FFmpeg》第一章彩色插图汇总

    layout: post title: "<深入理解 FFmpeg>第一章彩色插图" tags: - "FFmpeg" 这是<深入理解 FFm ...

  8. 【Buildroot】工具包使用

    一.测试环境 开发板:rv1126 buildroot版本:2018.02-rc3 二..mk规则 PKG_NAME:定义软件包的名称.通常与软件包源代码的目录名相同. PKG_VERSION:定义软 ...

  9. video和表单组件(不常用 类型太少)

    h5不能自动播放,只有在静音的前提下才能 button:(种类太少 不能满足需求) <button size="mini" type="primary" ...

  10. C++ Qt开发:ComboBox下拉组合框组件

    Qt 是一个跨平台C++图形界面开发库,利用Qt可以快速开发跨平台窗体应用程序,在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置,实现图形化开发极大的方便了开发效率,本章将重点介绍ComboBo ...