String、stringBuilder、stringBuffer——部分源码

String   不可变字符序列

定义

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

 因为有final修饰,所以String类不能被继承

实现了serializable接口,可以进行对象序列化

实现了comparable接口  对其中的compareTo方法进行了重写(后面分析)

实现了CharSequence接口,其实就是一个字符序列,stringbuffer和stringBuilder都实现了该接口,说明他们的底层都是字符数组实现的,也就是说字符串是Unicode字符序列组成

 

 变量

private final char value[];  //底层是数组实现 并且由final修饰,所以说是string是不可变的

 private int hash;  //哈希码  联想hashcode()函数

//反序列化时对比码
 private static final long serialVersionUID = -6849794470754667710L;

 

构造函数


/**
 *  无参构造方法
 *  因为string对象不可变,所以没必要调用此方法
 */
public String() {
        this.value = "".value;
    }

   /** 
    *  
    *  
    *  只将value指向了原来的数组
    */
   public String(String original) {
        this.value = original.value;
        this.hash = original.hash;
    }


/**
 *    以字符数组作为参数
 *    内部调用了 Arrays.copyOf(value, value.length) 
 *    只是将该数组复制到value中 
 *    Arrays.copyOf 又调用了System.arraycopy
 *    Arrays.copyOf 返回了一个新建的字符数组
 *    System.arraycopy 是一个本地方法 不是Java语言实现的
 */

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


public static char[] copyOf(char[] original, int newLength) {
        char[] copy = new char[newLength];
        System.arraycopy(original, 0, copy, 0,
                         Math.min(original.length, newLength));
        return copy;
    }


public static native void arraycopy(Object src,  int  srcPos,
                                        Object dest, int destPos,
                                        int length);

 

 功能函数

/**
 *    public String substring(int beginIndex)
 *    参数不在字符数组范围内将抛出数组越界异常
 *    截取传入参数及以后位置的字符所构成的字符串,包括起始位
 *    如果说从0开始,那就等于没有截取,所以返回当前字符串
 *    因为字符串为不可变的所以一旦被截取则返回新的字符串对象
 */
public String substring(int beginIndex) {
        if (beginIndex < 0) {
            throw new StringIndexOutOfBoundsException(beginIndex);
        }
        int subLen = value.length - beginIndex;
        if (subLen < 0) {
            throw new StringIndexOutOfBoundsException(subLen);
        }
        return (beginIndex == 0) ? this : new String(value, beginIndex, subLen);
    }


/**
 *    截取起始位到终止位之间字符所构成的字符串
 *    包括起始位置字符但不包括终止位
 *    其他与上述类似
 */
  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);
    }

replace函数(替换指定字符)


//1.替换字符时,如果要替换的字符和被替换的字符相等,则等效于没有替换,所以直接返回当前字符串
//2.当要替换的和被替换的字符不等时进入if语句里面继续执行,此时如果在字符串中找到被替换的字符
//则替换该字符   最终返回一个新的字符串
public String replace(char oldChar, char newChar) {
1        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];
  2                  buf[i] = (c == oldChar) ? newChar : c;
                    i++;
                }
                return new String(buf, true);
            }
        }
        return this;
    }

spilt切割函数  按指定规则进行字符串切割,返回一个字符串数组

trim去除首尾所有空格 

toCharArrary 返回该字符串对应的字符数组,此时返回的是个新的字符数组

 

 其他

/**
 * equals方法
 * 先直接==判断是否相等,相等返回true
 * 然后进行类型判断,为true则继续进行 否则返回false
 * 然后判断相应位置字符是否相等,一旦不等则返回false
 * 所有位置的字符相等才返回true
 * 根据这样的规则,所以字符串对象在使用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;
    }

 

 compareTo()

/**
 *    重写接口compareTo方法
 *    转换为字符数组进行操作,比较次数最多为两个字符串长度较小的
 *    字符可以与int相互转换,所以可以使用"-"操作符
 *    由数组首位开始进行比较
 *    当两个字符不等时,返回正数,所以默认是升序排列
 *    两个字符不等时继续下一个位置的字符比较
 */
public int compareTo(String anotherString) {
        int len1 = value.length;
        int len2 = anotherString.value.length;
        int lim = Math.min(len1, len2);
        char v1[] = value;
        char v2[] = anotherString.value;

        int k = 0;
        while (k < lim) {
            char c1 = v1[k];
            char c2 = v2[k];
            if (c1 != c2) {
                return c1 - c2;
            }
            k++;
        }
        return len1 - len2;
    }


	public static void main(String[] args) {
		String[] strings= {"apple","fool","appear","food","as"};
		Arrays.sort(strings);
		for (String string : strings) {
			System.out.println(string);
		}
	}
输出:
appear
apple
as
food
fool

 

 

 

stringBuilder  可变字符序列

定义

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

继承了一个抽象类AbstractStringBuilder

可以看出StringBuilder和StringBuffer都继承了该抽象类

同样是数组实现但是不同于string该数组并没有被final和private修饰

构造函数

//无参构造函数  里面调用父类的一个构造方法
public StringBuilder() {
        super(16);
    }

//创建大小为16字符数组并将引用赋值给value
AbstractStringBuilder(int capacity) {
        value = new char[capacity];
    }

//有参构造函数,指定字符数组的大小,同样调用上述父类的构造方法
  public StringBuilder(int capacity) {
        super(capacity);
    }

/** 构造方法  参数为字符串
 *  同样调用了父类的构造方法  数组长度为当前字符串长度加上16
 *  调用append方法 append方法又调用了父类的该方法 将字符串放入value中
 */
public StringBuilder(String str) {
        super(str.length() + 16);
        append(str);
    }

 public StringBuilder append(String str) {
        super.append(str);
        return this;
    }

 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;
    }

append用于追加字符串,从函数可以看出返回值始终为this  也就是说每次操作后返回的都是自己,即都是在操作同一个对象,

扩容

不同于string中的数组没有被限制,可变都是通过操作该数组来实现的

//确保容量   当超出容量后 重新new了数组并扩容然后替换之前的数组
private void ensureCapacityInternal(int minimumCapacity) {
        // overflow-conscious code
        if (minimumCapacity - value.length > 0) {
1            value = Arrays.copyOf(value,
2                   newCapacity(minimumCapacity));
        }
    }


1 public static char[] copyOf(char[] original, int newLength) {
        char[] copy = new char[newLength];
        System.arraycopy(original, 0, copy, 0,
                         Math.min(original.length, newLength));
        return copy;
    }

2 private int newCapacity(int minCapacity) {
        // overflow-conscious code
        int newCapacity = (value.length << 1) + 2;
        if (newCapacity - minCapacity < 0) {
            newCapacity = minCapacity;
        }
        return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0)
            ? hugeCapacity(minCapacity)
            : newCapacity;
    }

删除指定位置之间的字符串,取首不取尾 

 public StringBuilder delete(int start, int end)

 

 

底层的一些解释:https://www.cnblogs.com/dolphin0520/p/3778589.html 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值