面试官:请聊一聊String、StringBuilder、StringBuffer三者的区别
面试官:“小伙子,在日常的写代码过程中,使用过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[];
//...
}
我们从源码中可以总结出如下几点内容:
- String类被final关键字修饰,意味着它不可被继承;
- String的底层采用了final修饰的char数组,意味着它的不可变性;
- 实现了Serializable接口意味着它支持序列化;
- 实现了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三者的区别的更多相关文章
- java中String StringBuilder StringBuffer比较和效率(性能)测试
string stringbuilder stringbuffer三者的区别 从JDK源码看,String.StringBuilder.StringBuffer都是存放在char[] 数组字符串. 简 ...
- Java中的String,StringBuilder,StringBuffer三者的区别?
package com.aaa.zxf.ajax.test; /** * 弄清楚 string stringBuilder StringBuffer 三者之间的关系? * * * 一. 三者都是用来对 ...
- String,StringBuilder,StringBuffer三者的区别
参考 String,StringBuilder,StringBuffer三者的区别 这三个类之间的区别主要是在两个方面,即运行速度和线程安全这两方面. 1.运行速度 首先说运行速度,或者说是执行速 ...
- 33-Java中的String,StringBuilder,StringBuffer三者的区别
转载自:https://www.cnblogs.com/su-feng/p/6659064.html StringBuilder 详解 (String系列之2) Java中的String,String ...
- 深入源码剖析String,StringBuilder,StringBuffer
[String,StringBuffer,StringBulider] 深入源码剖析String,StringBuilder,StringBuffer [作者:高瑞林] [博客地址]http://ww ...
- JDK源码分析系列---String,StringBuilder,StringBuffer
JDK源码分析系列---String,StringBuilder,StringBuffer 1.String public final class String implements java.io. ...
- String, StringBuilder, StringBuffer问题
1. 区别 String为字符串常量,而StringBuilder和StringBuffer都是字符串变量,其中StringBuilder线程非安全,StringBuffer线程安全. 每次对 Str ...
- String StringBuilder StringBuffer区别
String StringBuilder StringBuffer String类是final类,不可以被继承,且它的成员方法也是final方法,当一个字符串对象进行操作操作时,任何的改变不会影响到这 ...
- difference among String,StringBuilder,StringBuffer
difference among String,StringBuilder,StringBuffer String常用构造函数 String(byte[] bytes) String(byte[] b ...
- Java—String,StringBuffer,StringBuilde区别和操作
Java语言有关字符串的类有三种 java.lang.String:一般作为简单字符串类型 java.lang.StringBuffer:字符串缓冲区 java.lang.StringBuider:字 ...
随机推荐
- 【教程】cpp转python Nanobind 实践 加速轻量版 pythonbind11
主要是尝试一下把c++这边的函数封装打包给python用,选择nanobind的原因是:1. 优化速度快,2. 生成二进制包小,不过pythonbind11是更为广泛知道的,nanobind也是pyt ...
- P1029 最大公约数和最小公倍数问题(普及−) 题解
题目传送门 想要做这题,我们要先了解一下最大公约数. 最大公因数,也称最大公约数.最大公因子,指两个或多 个整数共有约数中最大的一个.a,b的最大公约数记为 (a,b),同样的,a,b,c的最大公约数 ...
- 基于Redis的简易延时队列
基于Redis的简易延时队列 一.背景 在实际的业务场景中,经常会遇到需要延时处理的业务,比如订单超时未支付,需要取消订单,或者是用户注册后,需要在一段时间内激活账号,否则账号失效等等.这些业务场景都 ...
- kotlin+springboot入门级别教程,教你如何用kotlin和springboot搭建http
先打开idea,或者用springboot官网.阿里云那边都行 然后点击新建项目,spring Initializr,我们都知道,springboot是支持kotlin的,除非你是kotlin1.3之 ...
- 吉特日化MES & 医药行业相关专业术语汇总
- 1.5万字 + 25张图盘点RocketMQ 11种消息类型,你知道几种?
大家好,我是三友~~ 故事的开头是这样的 最近有个兄弟私信了我一张截图 我一看截图内容,好家伙,原来是我一年多前立的flag 倒不是我忘了这件事,我后来也的确写了一篇的关于RocketMQ运行的原理的 ...
- 《深入理解 FFmpeg》第一章彩色插图汇总
layout: post title: "<深入理解 FFmpeg>第一章彩色插图" tags: - "FFmpeg" 这是<深入理解 FFm ...
- 【Buildroot】工具包使用
一.测试环境 开发板:rv1126 buildroot版本:2018.02-rc3 二..mk规则 PKG_NAME:定义软件包的名称.通常与软件包源代码的目录名相同. PKG_VERSION:定义软 ...
- video和表单组件(不常用 类型太少)
h5不能自动播放,只有在静音的前提下才能 button:(种类太少 不能满足需求) <button size="mini" type="primary" ...
- C++ Qt开发:ComboBox下拉组合框组件
Qt 是一个跨平台C++图形界面开发库,利用Qt可以快速开发跨平台窗体应用程序,在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置,实现图形化开发极大的方便了开发效率,本章将重点介绍ComboBo ...