1. AbstractStringBuilder是StringBuffer和StringBuilder的父类
package com.amazing.jdk.string_2017_12_31; import java.util.Arrays; public abstract class MyAbstractStringBuilder { //用来存储字节 char[] value; //字节的数量 int count; private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; /** * 无参的构造方法 */ MyAbstractStringBuilder(){} /** * 有参的构造方法 * @param capacity * @return */ MyAbstractStringBuilder(int capacity){ value = new char[capacity]; } /** * 已存储字符长度 * @return */ public int length(){ return count; } /** * 字符数组长度 * @return */ public int capacity(){ return value.length; } /** * 确保不会数组下标越界 * length --->2*length+2 --->max_size---> Integer.Max * @param minimumCapacity */ public void ensureCapacity(int minimumCapacity){ if(minimumCapacity>0){ //大于0 if(minimumCapacity-value.length>0){ //长度大于字符数组长度(容量不够),进行扩容 int newCapacity = (value.length*2)+2; //位运算 (value.length << 1) + 2; if(newCapacity - minimumCapacity < 0){ //扩容两倍还是不够,就让数组长度等于传进来的数 newCapacity = minimumCapacity; } if(MAX_ARRAY_SIZE - minimumCapacity > 0){ value =Arrays.copyOf(value,newCapacity); }else { if(minimumCapacity>Integer.MAX_VALUE){ //超出内存错误 throw new OutOfMemoryError(); } value=Arrays.copyOf(value,minimumCapacity); } } } } /** * 对应下标的字符 * @param index * @return */ public char charAt(int index){ if(index<0 || index>=count){ throw new StringIndexOutOfBoundsException(index); } return value[index]; } /** * 追加:null * @return */ public MyAbstractStringBuilder appendNull(){ int c=count; ensureCapacity(c+4); final char[] value=this.value; value[c++] = 'n'; value[c++] = 'u'; value[c++] = 'l'; value[c++] = 'l'; count = c; return this; }
/**
* 追加内容 重写Appendable接口的方法
* @param c
* @return
*/
public MyAbstractStringBuilder append(char c){
ensureCapacity(count+1);
value[count++] = c;
return this;
}
/**
* 字符串逆序输出
* @param str
* @return
*/
public String reverse(String str){
char[] charStr = str.toCharArray();
int len = str.length();
int n = len-1;
for (int j = (n-1) >> 1; j >= 0; j--) {
int k = n - j;
char cj = charStr[j];
char ck = charStr[k];
charStr[j] = ck;
charStr[k] = cj;
}
return new String(charStr);
}
public abstract String toString(); //唯一的一个抽象方法:toString(),实现类重写该方法
final char[] getValue() { 唯一的一个final方法:getValue(),得到value数组。可以对其直接操作
return value;
}
}
2. 把一个字符串反转的方法:
public static String reverse1(String str){ return new StringBuffer(str).reverse().toString(); } public static String reverse2(String str){ char[] charStr = str.toCharArray();//把字符串转成字符数组 String reverse = "";//空数组用来装反转之后的字符串 for(int i=charStr.length-1;i>=0;i--){ //倒序遍历 reverse+=charStr[i]; } return reverse; } public static String reverse3(String str){ int len = str.length(); String reverse = ""; for (int i = 0; i <len ; i++) { reverse = str.charAt(i)+reverse; //倒着加,没啥卵用(效率不会提高) } return reverse; }
//注意理解这个算法 public static String reverse4(String str){ char[] charStr = str.toCharArray(); int len = str.length(); int n = len-1; for (int j = (n-1) >> 1; j >= 0; j--) { int k = n - j; char cj = charStr[j]; char ck = charStr[k]; charStr[j] = ck; charStr[k] = cj; } return new String(charStr); }
3.注意:
AbstractStringBuilder的两者都是可变的,并且也定义了getValues方法让我们可以直接拿到value[],value实际上是个动态数组,和ArrayList的实现有很多相似的地方
注意和String的区别
4.该抽象类实现的接口
(1).CharSequence接口
public interface CharSequence{
int length(); //字符序列长度
char charAt(int index); //取得下标为index的字符
CharSequence subSequence(int start, int end); //得到该字符序列的一个子序列
public String toString(); //规定了该字符序列的String版本
}
实现这个接口的类都会重写这四个方法
(2).public interface Appendable{
Appendable append(char c) 向此 Appendable 添加指定字符。
Appendable append(CharSequence csq) 向此 Appendable 添加指定的字符序列。
Appendable append(CharSequence csq, int start, int end)向此 Appendable 添加指定字符序列的子序列。
}
Appendable接口:
Appendable接口的实现类的对象能够被添加 char 序列和值。(像IO里的类就实现了这个接口)
如果某个泪的实例打算接收取自Formatter的格式化输出,那么这个类必须实现Appendable接口,
格式化主要用在文本输出方面,比如:数字,日期,金额等。