从源码看String,StringBuffer,StringBuilder的区别
前言
看了一篇文章,大概是讲面试中的java基础的,有如题这么个面试题。我又翻了一些文章看了下,然后去看源码。看一下源码大概能更加了解一些。
String
String类是final的,表示不可被继承,不可变的。注释上也有说明:

其中用一个char[]来保存String的值。
private final char value[];
一旦赋值,就不可改变。看一下,操作string的源码,例如 substring,replace,concat 等方法,最终结果都是返回 new String(...). 也就是重新创建了一个String对象。
public String substring(int beginIndex, int endIndex) {
if (beginIndex < 0) {
throw new StringIndexOutOfBoundsException(beginIndex);
}
if (endIndex > value.length) {
throw new StringIndexOutOfBoundsException(endIndex);
}
int subLen = endIndex - beginIndex;
if (subLen < 0) {
throw new StringIndexOutOfBoundsException(subLen);
}
return ((beginIndex == 0) && (endIndex == value.length)) ? this
: new String(value, beginIndex, subLen);
}
public String concat(String str) {
int otherLen = str.length();
if (otherLen == 0) {
return this;
}
int len = value.length;
char buf[] = Arrays.copyOf(value, len + otherLen);
str.getChars(buf, len);
return new String(buf, true);
}
public String replace(char oldChar, char newChar) {
if (oldChar != newChar) {
int len = value.length;
int i = -1;
char[] val = value; /* avoid getfield opcode */
while (++i < len) {
if (val[i] == oldChar) {
break;
}
}
if (i < len) {
char buf[] = new char[len];
for (int j = 0; j < i; j++) {
buf[j] = val[j];
}
while (i < len) {
char c = val[i];
buf[i] = (c == oldChar) ? newChar : c;
i++;
}
return new String(buf, true);
}
}
return this;
}
StringBuffer 和 StringBuilder
它两个都是继承自 AbstractStringBuilder 抽象类,不同的是StringBuffer类都是带有 synchronized 关键字的。也就是说,StringBuffer是线程安全的,而 StringBuilder不是。他们中的方法基本上调用 super的方法。也就是AbstractStringBuilder 里实现的方法。
平时用的比较多的就是 append 方法。我们看一下代码实现:
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;
}
private void ensureCapacityInternal(int minimumCapacity) {
// 当append之后的长度大于当前value的长度的时候,需要重新生成一个char[]数组。
if (minimumCapacity - value.length > 0) {
value = Arrays.copyOf(value,
newCapacity(minimumCapacity));
}
}
public static char[] copyOf(char[] original, int newLength) {
//重新创建一个char[]数组
char[] copy = new char[newLength];
//将之前的值赋值到该数组中
System.arraycopy(original, 0, copy, 0,
Math.min(original.length, newLength));
return copy;
}
ensureCapacityInternal 方法中,将 value的值重新扩展比如 str.append("abc")。假如之前value的值为:{'h','e','l','l','o'},当调用 str.getChars方法之后,会将 abc 追加到value数组后,value值就变成 :{'h','e','l','l','o','a','b','c'}
其实 getChars 方法只是做了一件事情 :System.arraycopy。
如图:

执行完arraycopy之后

总结
String 不可变,StringBuffer和StringBuilder可变,但是StringBuilder非线程安全。可以根据他们不同的特性分情况使用。
从源码看String,StringBuffer,StringBuilder的区别的更多相关文章
- String,StringBuffer,StringBuilder的区别及其源码分析
String,StringBuffer,StringBuilder的区别这个问题几乎是面试必问的题,这里做了一些总结: 1.先来分析一下这三个类之间的关系 乍一看它们都是用于处理字符串的java类,而 ...
- [置顶] String StringBuffer StringBuilder的区别剖析
这是一道很常见的面试题目,至少我遇到过String/StringBuffer/StringBuilder的区别:String是不可变的对象(final)类型,每一次对String对象的更改均是生成一个 ...
- 从源码看commit和commitAllowingStateLoss方法区别
Fragment介绍 在很久以前,也就是我刚开始写Android时(大约在2012年的冬天--),那时候如果要实现像下面微信一样的Tab切换页面,需要继承TabActivity,然后使用TabHost ...
- String,StringBuffer,StringBuilder的区别
public static void main(String[] args) { String str = new String("hello...."); StringBuffe ...
- Question 20171115 String&&StringBuffer&&StringBuilder的区别与联系?
Question 20171114 String&&StringBuffer&&StringBuilder的区别和联系 创建成功的String对象,其长度是固定的,内容 ...
- JDK源码分析-String、StringBuilder、StringBuffer
String类的申明 public final class String implements java.io.Serializable, Comparable<String>, Char ...
- java中 String StringBuffer StringBuilder的区别
* String类是不可变类,只要对String进行修改,都会导致新的对象生成. * StringBuffer和StringBuilder都是可变类,任何对字符串的改变都不会产生新的对象. 在实际使用 ...
- 深入理解String, StringBuffer, StringBuilder的区别(基于JDK1.8)
String.StringBuffer.StringBuilder都是JAVA中常用的字符串操作类,对于他们的区别大家也都能耳熟能详,但底层到底是怎样实现的呢?今天就再深入分析下这三种字符串操作的区别 ...
- Android/Java 中的 String, StringBuffer, StringBuilder的区别和使用
Android 中的 String, StringBuffer 和 StringBuilder 是移动手机开发中经常使用到的字符串类.做为基础知识是必须要理解的,这里做一些总结. A.区别 可以从以下 ...
随机推荐
- spring security入门
1. Restful API和传统API的区别 用URL描述资源 用http描述方法行为,用http状态码描述结果 使用json交互数据 RESTful是一种风格,不是强制的标准 2. 使用sprin ...
- java中list、set、map区别(转)
Collection├List│├LinkedList│├ArrayList│└Vector│ └Stack└SetMap├Hashtable├HashMap└WeakHashMap Collecti ...
- rabbit工作队列模式
工作队列比简单队列在消费者这边多了一个方法. channel.basicQos(1);公平队列消费(参数设置为1,表示消费者消费完一条才会去接受再次发来的消息) 生产者: package com.kf ...
- IntelliJ IDEA 安装配置
之前一直用的eclipse,以前公司的老大推荐过用这个,但是由于项目都比较赶,没及时学习. 后面这个公司的同时都用的idea,所以就换了 其实并没有那么难主要是刚刚切换时候快捷键不熟悉,打包什么的,有 ...
- 深入理解jQuery插件开发总结(四)
jQuery插件开发模式 软件开发过程中是需要一定的设计模式来指导开发的,有了模式,我们就能更好地组织我们的代码,并且从这些前人总结出来的模式中学到很多好的实践. 根据<jQuery高级编程&g ...
- [转]Shared——Javascript中的call详解
call( ) 一.call的使用 call 方法第一个参数是作为函数上下文的对象,第二个参数是一个参数列表. var obj = { name: 'J' } function func(p1, p2 ...
- asp.net core 错误定位 & vs2017 远程调试部署在centos上的asp.net core程序
前言 程序运行中会出现各种BUG. 排除BUG有三种方式. 一.访问页面直接报错误信息 出于安全,服务器是关闭这个功能的.在centos上可以用 命令设置环境变量来解决: export A ...
- sqlserver2008数据库文件降级为sqlserver2005文件
直接分离附加是不行的. 操作步骤如下: 在sqlserver2008企业管理器中 右键xx数据库->任务->生成脚本 弹出框中勾选 为所选数据库中的所有对象编写脚本 下一步 修改如下图片 ...
- 1-4 Sass的基本特性-基础
[Sass]声明变量 定义变量的语法: 在有些编程语言中(如,JavaScript)声明变量都是使用关键词“var”开头,但是在 Sass 不使用这个关键词,而是使用大家都喜欢的美元符号“$”开头.我 ...
- 04_zookeeper的watcher机制
[watcher简述] * zk针对每个节点的操作,都会有一个监督者:watcher * 当监控的某个对象(znode)发生了变化,则出发watcher * zk中的watcher是一次性的,出发后立 ...