java源代码之StringBuffer,StringBuilder,String类三个的关系

不看你绝对后悔

1、看String类的定义

(1)基本的定义

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    
    private final char value[];

    private int hash; // Default to 0

    private static final long serialVersionUID = -6849794470754667710L;

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

  • 它实现了java.io.SerializableComparable<String>CharSequence三大接口【马上讲解三大接口】
  • final char value[]定义的一个char数组【原来如此,用final定义了,不能修改的原因】
  • Comparable这个接口不讲,我主页讲过Comparable和Comparator的文章,可以去参考

(2)看它的构造方法

    //不用看内部实现
    public String() {
        this.value = "".value;
    }

	//不用看内部实现
    public String(String original) {
        this.value = original.value;
        this.hash = original.hash;
    }

  	//不用看内部实现
    public String(char value[], int offset, int count) {
        
    }

    //不用看内部实现
    public String(int[] codePoints, int offset, int count) {
      
    }

    
    @Deprecated
    public String(byte ascii[], int hibyte, int offset, int count) 
    
    }

   
    
    @Deprecated
    public String(byte ascii[], int hibyte) {
        
    }

在这里插入图片描述
从上面我们可以收获如下东西

  • @Deprecated:这个注解,是表示这个方法是过期的。
  • @NotNull注解:可以看这篇文章,大致也就是就是不能为这个参数不能为null,你实例化的时候不能什么都不填

2、看StringBuffer和StringBuilder

(1)先看StringBuffer

 public final class StringBuffer
 		extends AbstractStringBuilder
    	implements java.io.Serializable, CharSequence {

	private transient char[] toStringCache;

    static final long serialVersionUID = 3388685877147921107L;
    
    public StringBuffer() {
        super(16);
    }

    public StringBuffer(int capacity) {
        super(capacity);
    }
 
    public StringBuffer(String str) {
        super(str.length() + 16);
        append(str);
    }

    public StringBuffer(CharSequence seq) {
        this(seq.length() + 16);
        append(seq);
    }

从里面可以获得如下东西

  • 继承了AbstractStringBuilder抽象类,实现了:java.io.Serializable, CharSequence接口
  • 内部定义了:toStringCache的char数组进行数据的处理
  • 然后其他的方法就是都用到了关键字:synchronized定义的方法实现了线程同步【这个就是和StringBuilder的区别所在,这样会降低速度】
  • 其次是构造方法:你可以这样public StringBuffer()直接定义一个StringBuffer类来完成操作,它默认toStringCache大小为16进行操作,下次是自动添加16,不会导致栈溢出的问题。你也可以通过public StringBuffer(int capacity)指定实力话大小,进行操作。
    在这里插入图片描述

(2)再来看StringBuilder

public final class StringBuilder
    extends AbstractStringBuilder
    implements java.io.Serializable, CharSequence
{

    static final long serialVersionUID = 4383685877147921099L;

    public StringBuilder() {
        super(16);
    }

   
    public StringBuilder(String str) {
        super(str.length() + 16);
        append(str);
    }

   
    public StringBuilder(CharSequence seq) {
        this(seq.length() + 16);
        append(seq);
    }
  • 同样的继承了AbstractStringBuilder抽象类,实现了:java.io.Serializable, CharSequence接口
  • 其他的构造方法呀,都和上面个类一样
  • 但是它居然连一个存储数据的数组都不给,但是它调用的super点进去就跳到了AbstractStringBuilder类里面去了,去康康这个类

(3)AbstractStringBuilder

abstract class AbstractStringBuilder implements Appendable, CharSequence {
    
    char[] value;

    int count;
 
    AbstractStringBuilder() {
    }
    
    AbstractStringBuilder(int capacity) {
        value = new char[capacity];
    }
  • 它也实现了Appendable, CharSequence接口
  • 原理保存数据的数组在这里面定义了

这里的小总结:我们通过AbstractStringBuilder定义了一些统一的操作,StringBuffer和StringBuilder都实现了这个抽象类来执行共同的操作,不同点在一个用了关键字synchronized定义了方法,实现线程同步,都是初始化了16的数组大小来完成操作

3、再来看他们三个的共同点

(1)public interface Appendable接口

  • 这个接口已经走到了本次继承关系的尽头【没有再去实现其他接口什么的了】
    在这里插入图片描述
  • 来看它的源代码
package java.lang;

import java.io.IOException;

/**
 * An object to which <tt>char</tt> sequences and values can be appended.  The
 * <tt>Appendable</tt> interface must be implemented by any class whose
 * instances are intended to receive formatted output from a {@link
 * java.util.Formatter}.
	/**
 * 可以将字符序列和值追加到其中的对象。
 * Appendable接口必须实现,该类的实例旨在从java.util.Formatter接收格式化的输出。
 *
 * <p> The characters to be appended should be valid Unicode characters as
 * described in <a href="Character.html#unicode">Unicode Character
 * Representation</a>.  Note that supplementary characters may be composed of
 * multiple 16-bit <tt>char</tt> values.
 *
 * <p> Appendables are not necessarily safe for multithreaded access.  Thread
 * safety is the responsibility of classes that extend and implement this
 * interface.
 *
 * <p> Since this interface may be implemented by existing classes
 * with different styles of error handling there is no guarantee that
 * errors will be propagated to the invoker.
 * <p> 对于多线程访问来说,Appendables不一定是安全的。
 * 线程安全是扩展和实现这个接口的类的职责。
 *
 * <p> 由于这个接口可以由具有不同风格的错误处理的现有类实现,因此不能保证错误将传播到调用程序。
 * @since 1.5
 */
public interface Appendable {

}

说人话就是总结如下

  • 接口是非线程安全的
  • 如果要去修改我们的char定义的对象,那你必须实例化这个接口

(2)public interface CharSequence接口

不难发现我们三个类:StringBuffer,StringBuilder,String都实现了CharSequence接口,那他到底是干嘛的呢?
在这里插入图片描述
在这里插入图片描述
下面这些方法都熟悉吧
在这里插入图片描述
原来如此:这个类接口定义了实现这个接口的类,必须实现的一些方法,计算其长度啊,所以你的String,StringBuffer等都可以计算长度,获得第一个字母等方法,所以理解了吧,CharSequence定义了标准,让你实现类去实现。

(3)public interface java.io.Serializable

这个的话,太简单了,就是为了方便在网上传输,然后就可以实现这个接口,它内部实现了。但是,但是,但是,请你记住,你要在网上传输的类都请实现这个接口

4、总结

(1)本次的收获

  • 了解了他们几个的关系吧
  • 知道了他们操作的流程吧
  • 了解了继承关系吧
  • 补充了自己不知道的几个接口吧
  • 反正都是那玩意,你理解就可以了

(2)补充知识1

是这样的一个问题:我们每次实话一个StringBuffer或者StringBuilder对象都是实例化长度都是16,如果我们一直对字符串进程添加知道超过初始化定义的长度会不会报错呢?

  • 答案是不会的
  • 因为我们再进去康康添加的方法:点StringBuffer或者StringBUilder都可以,都会走到我们的AbstractStringBuilder类里面的添加方法
    在这里插入图片描述
    • 观察方法不难发现都在天机方法里面调用了ensureCapacityInternal方法,去康康ensureCapacityInternal是何方神圣
      在这里插入图片描述
    • ensureCapacityInternal又去调佣了newCapacity,哦,懂了懂了,它在每次都会去判断是否会超过其长度,如果超过了翻一倍其长度+2 。所以不会有栈溢出的情况发生。

但是,但是,但是上面讲解的情况不是下面的这种情况哦【自己想一下为什么】
在这里插入图片描述

(3)补充知识2

  • 问题:String str = new String(“xxx”)和String str = “xxx”;一样吗?
  • 问题:String str1 = new String(“AAA”);String str2 = new String(“AAA”);str1和Str2一样吗

答案:是不一样
在这里插入图片描述

  • 为什么呢?可以自己去找找看,我这就不详细讲解了,是关于java内存结构和常量池的一些关系

(3)补充知识3

  • 问题:都说String定义了的常量是不能修改的,并且JDK也自己没有提供可修改的方法?比如:String str = “xxx”,
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值