JDK 1.8 源码解析 String、StringBuilder和StringBuffer的异同

  JDK提供了String、StringBuilder和StringBuffer这三个类来处理字符串,其中StringBuilder类是在JDK 1.5中新增的。

  不同点如下:

  1 是否有父类

  String没有父类。

// String类不能被继承
// 实现了Serializable、Comparable和CharSequence(字符序列)接口
public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence

  StringBuilder和StringBuffer都继承了抽象类AbstractStringBuilder。

// 抽象类AbstractStringBuilder
// 实现了Appendable(可追加)和CharSequence(字符序列)接口
abstract class AbstractStringBuilder implements Appendable, CharSequence
1 // StringBuilder类不能被继承
2 // 继承了抽象类AbstractStringBuilder
3 // 实现了Serializable和CharSequence接口
4 public final class StringBuilder
5     extends AbstractStringBuilder
6     implements java.io.Serializable, CharSequence
1 // StringBuffer类不能被继承
2 // 继承了抽象类AbstractStringBuilder
3 // 实现了Serializable和CharSequence接口
4 public final class StringBuffer
5     extends AbstractStringBuilder
6     implements java.io.Serializable, CharSequence

  2 可变性

  属性字符数组不可变(数组引用不可变,数组元素可变),String不可变,对于每个不同的字符串都需要一个单独的String对象。

// 字符数组
private final char value[];

  AbstractStringBuilder中的字符数组可变,StringBuilder和StringBuffer可变。StringBuilder和StringBuffer都有insert()插入方法、delete()删除方法和append()末尾追加方法,调用System.arraycopy()方法来实现数组元素的拷贝。

// 字符数组
char[] value;

  3 是否线程安全

  String对象不可变,本质上是线程安全的。StringBuilder和StringBuffer的方法实现大致相同,不同之一是StringBuffer类的方法上加了synchronized关键字,即加了对象锁,该锁会锁住整个对象,效率低。也就是说,StringBuffer是线程安全的。

// 获取子串顺序下从某位置开始首次出现的位置
@Override
public int indexOf(String str, int fromIndex) {
    return super.indexOf(str, fromIndex);
}

  

@Override
public synchronized int indexOf(String str, int fromIndex) {
    return super.indexOf(str, fromIndex);
}

  相同点如下:

  1 substring()方法(截取字符串,即获取子串)

  String中的substring()方法:

 1 // 截取字符串
 2 public String substring(int beginIndex, int endIndex) {
 3     if (beginIndex < 0) { // 如果起始下标<0
 4         throw new StringIndexOutOfBoundsException(beginIndex);
 5     }
 6     if (endIndex > value.length) { // 如果末尾下标>字符数组长度
 7         throw new StringIndexOutOfBoundsException(endIndex);
 8     }
 9     int subLen = endIndex - beginIndex; // 获取截取长度
10     if (subLen < 0) { // 如果截取长度<0
11         throw new StringIndexOutOfBoundsException(subLen);
12     }
13     return ((beginIndex == 0) && (endIndex == value.length)) ? this
14             : new String(value, beginIndex, subLen);
15 }

  AbstractStringBuilder中的substring()方法:

 1 // 获取子串,返回String对象的引用
 2 public String substring(int start, int end) {
 3     if (start < 0) // 如果开始位置<0
 4         throw new StringIndexOutOfBoundsException(start);
 5     if (end > count) // 如果结束位置>count
 6         throw new StringIndexOutOfBoundsException(end);
 7     if (start > end) // 如果开始位置>结束位置
 8         throw new StringIndexOutOfBoundsException(end - start);
 9     // 返回String对象的引用
10     return new String(value, start, end - start);
11 }

  substring()方法都是创建新的String对象并返回该对象引用。

  总结

  String适用于常量,StringBuilder适用于非并发情况下的字符串操作,StringBuffer适用于并发情况下的字符串操作。

  参考资料

  从Java源码角度彻底理解String,StringBuilder和StringBuffer的区别

  《Effective Java 中文版 第2版》 P66-67

原文地址:https://www.cnblogs.com/WJQ2017/p/8409880.html

时间: 2024-08-25 11:26:41

JDK 1.8 源码解析 String、StringBuilder和StringBuffer的异同的相关文章

jdk下httpserver源码解析

在写这篇博客之前我查了很久发现全网都没有一篇写httpserver源码解析的 所以今天就由我来为大家解析一下httpserver的源码.(这里我会去掉其中的https部分的源码,只讲http部分,对httpserver中https的实现感兴趣的读者可以尝试自己去阅读,这部分并不复杂) 第一次在没有参考资料的情况下写这么长一篇源码解析,可能会有很多错误和讲不清楚的地方,希望大家尽量指出来. 本文链接 https://www.cnblogs.com/fatmanhappycode/p/1261442

JDK核心JAVA源码解析(1) - Object

想写这个系列很久了,对自己也是个总结与提高.原来在学JAVA时,那些JAVA入门书籍会告诉你一些规律还有法则,但是用的时候我们一般很难想起来,因为我们用的少并且不知道为什么.知其所以然方能印象深刻并学以致用. 首先我们从所有类的父类Object开始: 1. Object类 (1)hashCode方法和equals方法 public native int hashCode(); public boolean equals(Object obj) { return (this == obj); }

Java源码解析|String源码与常用方法

String源码与常用方法 1.栗子 代码: public class JavaStringClass { public static void main(String[] args) { String s ="hello"; s = "world"; //内存地址已经修改 原来地址上的值还是不变的 String s2 = "hello"; //从常量值中找到并引用 String s4 = new String("hello"

JDK 1.8 源码解析 LinkedList

package java.util; // LinkedList继承了AbstractSequentialList // 实现了List.Deque.Cloneable和Serializable接口 public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, Deque<E>, Cloneable, java.io.Serializable // 元素数量

JDK 1.8 源码解析 ConcurrentHashMap

JDK 1.7中ConcurrentHashMap 基本结构: 每一个segment都是一个HashEntry<K,V>[] table, table中的每一个元素本质上都是一个HashEntry的单向队列.比如table[3]为首结点,table[3]->next为结点1,之后为结点2,依次类推. 1 public class ConcurrentHashMap<K, V> extends AbstractMap<K, V> 2 implements Concu

JDK 1.8 源码解析 PriorityQueue

package java.util; public class PriorityQueue<E> extends AbstractQueue<E> implements java.io.Serializable // 序列化版本号 private static final long serialVersionUID = -7720805057305804111L; // 默认初始容量 private static final int DEFAULT_INITIAL_CAPACITY

JDK 1.8 源码解析 HashSet

package java.util; // HashSet继承了AbstractSet,实现了Set.Cloneable和java.io.Serializable接口 public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, java.io.Serializable // 序列化版本号 static final long serialVersionUID = -5024744

JDK源码及其他框架源码解析随笔地址导航

置顶一篇文章,主要是整理一下写过的JDK中各个类的源码解析以及其他框架源码解析的文章,方便自己随时阅读也方便网友朋友们阅读及指正 基础篇 从为什么String=String谈到StringBuilder和StringBuffer Java语法糖1:可变长度参数以及foreach循环原理 Java语法糖2:自动装箱和自动拆箱 集合篇 图解集合1:ArrayList 图解集合2:LinkedList 图解集合3:CopyOnWriteArrayList 图解集合4:HashMap 图解集合5:不正确

死磕 Java 系列(一)&mdash;&mdash; 常用类(1) String 源码解析

写在前面 这是博主新开的一个 java 学习系列,听名字就可以看出来,在这一些系列中,我们学习的知识点不再是蜻蜓点水,而是深入底层,深入源码.由此,学习过程中我们要带着一股钻劲儿,对我们不懂的知识充满质疑,力求把我们学过的知识点都搞清楚,想明白. 一.引言 在 java 的世界里,存在一种特殊的类,它们的创建方式极为特别,不需要用到 new XXX(当然也可以用这种方式创建), 但是却大量出现在我们的代码中,那就是 String 类.作为日常中使用频率最高的类,它是那么普通,普通到我们从来都不会