String、StringBuffer、StringBuilder介绍

本文深入分析了Java中的String、StringBuilder和StringBuffer类,详细讲解了它们的继承关系、底层数据结构、构造器以及常用方法。String是不可变对象,其内部由final byte数组构成,而StringBuilder和StringBuffer则提供了可变字符串的功能,其中StringBuffer线程安全。文章还对比了三者的性能和适用场景,指出在单线程环境下StringBuilder更快,多线程时推荐使用StringBuffer。

String 源码分析

继承关系

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence

final修饰的类 不可以被继承
在这里插入图片描述

CharSequence

CharSequence类是java.lang包下的一个接口,此接口对多种不同的对char访问的统一接口,像String、StringBuffer、StringBuilder类都是CharSequence的子接口;

CharSequence类和String类都可以定义字符串,但是String定义的字符串只能读,CharSequence定义的字符串是可读可写的;

对于抽象类或者接口来说不可以直接使用new的方式创建对象,但是可以直接给它赋值;
用法:

CharSequence a = “abc”; 等价于: CharSequence a = new String(“abc”);

底层数据结构

 private final byte[] value; 

底层是被final修饰的byte数组,说明String 对象不可被更改。Java 实现的这个特性叫作 String 对象的不可变性,即 String 对象一旦创建成功,就不能再对它进行改变。

常用构造器:

无参构造器

public String() {
        this.value = "".value;
        
    }

返回空字符串的数组形式。

入参为String类型

public String(String original) {
        this.value = original.value;
        
        this.hash = original.hash;
    }

返回原来String对象的各个参数

入参为char数组类型

public String(char value[]) {
        this.value = Arrays.copyOf(value, value.length);
    }

public String(char value[], int offset, int count) {
        if (offset < 0) {
            throw new StringIndexOutOfBoundsException(offset);
        }
        if (count <= 0) {
            if (count < 0) {
                throw new StringIndexOutOfBoundsException(count);
            }
            if (offset <= value.length) {
                this.value = "".value;
                return;
            }
        }
        // Note: offset or count might be near -1>>>1.
        if (offset > value.length - count) {
            throw new StringIndexOutOfBoundsException(offset + count);
        }
        this.value = Arrays.copyOfRange(value, offset, offset+count);
    }

Arrays.copyOf方法进行数组拷贝的

入参为StringBuffer:

public String(StringBuffer buffer) {
        synchronized(buffer) {
            this.value = Arrays.copyOf(buffer.getValue(), buffer.length());
        }
    }

加锁进行拷贝,保证StringBuffer的线程安全

入参为StringBuilder:

 public String(StringBuilder builder) {
        this.value = Arrays.copyOf(builder.getValue(), builder.length());
    }

对比StringBuffer入参,如果用StringBuilder作为入参是不加锁操作的,因为StringBuilder本身线程不安全,但会提升性能。

常用方法

int length()

public int length() {
        return value.length;
    }

语法:字符串变量名.length();  
返回值为 int 类型。得到一个字符串的字符个数(中、英、空格、转义字符皆为字符,计入长度)

equals()

public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            int n = value.length;
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }

字符串内容比较

char charAt(int index);

语法 :字符串名.charAt(值);  
返回值为 char 类型。从字符串中取出指定位置的字符

char toCharArray();

语法 :字符串名.toCharArray();  
返回值为 char 数组类型。将字符串变成一个字符数组

int indexOf(char c)

语法 :字符串名.indexOf(“字符”);字符串名.indexOf(“字符”,值);
查找一个指定的字符串是否存在,返回的是字符串的位置,如果不存在,则返回-1 。

in lastIndexOf(char c)

得到指定内容最后一次出现的下标

toUpperCase(); toLowerCase();

字符串大小写的转换

split(char c)

根据给定的正则表达式的匹配来拆分此字符串。形成一个新的String数组。

trim()

去掉字符串左右空格

replace(char oldChar,char newChar)

新字符替换旧字符,也可以达到去空格的效果一种。

substring(int beginIndex,int endIndex)

截取字符串

equalsIgnoreCase(String)

忽略大小写的比较两个字符串的值是否一模一样,返回一个布尔值

contains(String)

判断一个字符串里面是否包含指定的内容,返回一个布尔值

String,StringBuffer与StringBuilder的区别

三者共同之处

都是final类,不允许被继承,主要是从性能和安全性上考虑的,因为这几个类都是经常被使用着,且考虑到防止其中的参数被参数修改影响到其他的应用。

各自的特点

StringBuffer是线程安全,可以不需要额外的同步用于多线程中;
StringBuilder是非同步,运行于多线程中就需要使用着单独同步处理,但是速度就比StringBuffer快多了;
StringBuffer与StringBuilder两者共同之处:可以通过append、indert进行字符串的操作。
String实现了三个接口:Serializable、Comparable、CarSequence

StringBuilder只实现了两个接口Serializable、CharSequence,相比之下String的实例可以通过compareTo方法进行比较,其他两个不可以。

主要区别:

运行速度

首先说运行速度,或者说是执行速度,在这方面运行速度快慢为:StringBuilder > StringBuffer > String
String最慢的原因:String为字符串常量,而StringBuilder和StringBuffer均为字符串变量,即String对象一旦创建之后该对象是不可更改的,但后两者的对象是变量,是可以更改的。

线程安全

在线程安全上,StringBuilder是线程不安全的,而StringBuffer是线程安全的
 如果一个StringBuffer对象在字符串缓冲区被多个线程使用时,StringBuffer中很多方法可以带有synchronized关键字,所以可以保证线程是安全的,但StringBuilder的方法则没有该关键字,所以不能保证线程安全,有可能会出现一些错误的操作。所以如果要进行的操作是多线程的,那么就要使用StringBuffer,但是在单线程的情况下,还是建议使用速度比较快的StringBuilder。

(一个线程访问一个对象中的synchronized(this)同步代码块时,其他试图访问该对象的线程将被阻塞)

各自适用场景

String:适用于少量的字符串操作的情况
StringBuilder:适用于单线程下在字符缓冲区进行大量操作的情况
StringBuffer:适用多线程下在字符缓冲区进行大量操作的情况
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值