String、StringBuffer和StringBuilder的区别:
首先String内部的字符数组是使用final修饰,无法修改,每次修改其实是创建一个新的String对象,为了高效字符串操作,引入了StringBuffer和StringBuilder。但StringBuffer的线程是安全的,适合多线程环境下使用,而StringBuilder速度快,但不安全,适合单线程环境下使用。
封装、继承、多态具体含义:
封装:将对象实现细节隐藏,只允许通过公共的接口与外部交互 (数据的安全性,代码可维护性)
继承:子类继承父类后,可获得父类公有的属性和方法(代码的复用性,扩展性)
多态:子类重写父类的方法,将子类对象赋给父类变量,但运行表现子类行为(代码可维护性,解耦合)
String
最多可以放多少个字符?
使用 char[]来维护字符序列的,而char[]的长度是 int类型,所以理论上 String的长度最大为2^31-1,不过根据实际JVM的堆内存限制,编译时,String长度最多可以是2的16次方减2。
源码分析:
substring(int beginIndex, int endIndex)
int length = length();//获取当前字符串的长度
checkBoundsBeginEnd(beginIndex, endIndex, length);//判断传入的参数是否合法
/*if (begin < 0 || begin > end || end > length) {
throw new StringIndexOutOfBoundsException(
"begin " + begin + ", end " + end + ", length " + length);
}*/
int subLen = endIndex - beginIndex;//获取截取字符长度
if (beginIndex == 0 && endIndex == length) {//如果起始点为0并且未位置等于当前字符串长度
return this;//返回本字符串
}
//否则根据编码方式新建子字符串
return isLatin1() ? StringLatin1.newString(value, beginIndex, subLen)
: StringUTF16.newString(value, beginIndex, subLen);
public int indexOf(String str)//查找子串,返回第一个找到的索引位置,没找到返回-1
//首先根据编码方式进行判断
if (str.length == 0) {//如果查找子串为空返回0
return 0;
}
if (length(value) < str.length) {//如果子串长度大于当前字符长度肯定找不到返回-1
return -1;
}
/*src:要搜索的源字节数组。
srcCount:源字节数组中的有效字节数。
tgt:要查找的目标字节数组。
tgtCount:目标字节数组中的有效字节数。
fromIndex:开始搜索的索引位置(包含)*/
public static int indexOfLatin1Unsafe(byte[] src, int srcCount, byte[] tgt, int tgtCount, int fromIndex) {
//确保数据合法
assert fromIndex >= 0;
assert tgtCount > 0;
assert tgtCount <= tgt.length;
assert srcCount >= tgtCount;
//转换字符
char first = (char)(tgt[0] & 0xff);
int max = (srcCount - tgtCount);//获取遍历次数,因为次数大于该值后src子字符串长度小于查找字符串所有肯定不成立
for (int i = fromIndex; i <= max; i++) {
// 找第一个匹配的字符
if (getChar(src, i) != first) {
while (++i <= max && getChar(src, i) != first);
}
// 还在范围内进入if
if (i <= max) {
int j = i + 1;
int end = j + tgtCount - 1;//尾位置
//遍历比对字符是否相同
for (int k = 1;
j < end && getChar(src, j) == (tgt[k] & 0xff);
j++, k++);
if (j == end) {
// 到达末尾说明找到,直接返回
return i;
}
}
}
return -1;
}
public boolean equals(Object anObject) //与其他字符串比较,看内容是否相同
public boolean equals(Object anObject) {
//判断是否是同一个对象,是则内容肯定相同
if (this == anObject) {
return true;
}
//判断该对象是否是String类
if (anObject instanceof String) {
//根据字符串判断是否一样
String aString = (String)anObject;
//根据编码方式进行判断
if (coder() == aString.coder()) {
return isLatin1() ? StringLatin1.equals(value, aString.value)
: StringUTF16.equals(value, aString.value);
}
//上述equals方法内代码
//如果长度不一样返回false
if (value.length == other.length) {
//一个个比较是否相同
for (int i = 0; i < value.length; i++) {
//不同返回false
if (value[i] != other[i]) {
return false;
}
}
return true;
}
return false;
}
//不是字符串返回false
return false;
}
public int compareTo(String anotherString) //比较字符串大小
//获取两个字符串长度
int len1 = value.length;
int len2 = other.length;
return compareTo(value, other, len1, len2);
public static int compareTo(byte[] value, byte[] other, int len1, int len2) {
//获取最短数组长度
int lim = Math.min(len1, len2);
//遍历
for (int k = 0; k < lim; k++) {
//不相等即可退出
if (value[k] != other[k]) {
return getChar(value, k) - getChar(other, k);
}
}
//返回长度差 0——相等 负数——本字符串小于比较的字符串 正数——本字符串大于比较的字符串
return len1 - len2;
}
public String concat(String str) //字符串连接,返回当前字符串和参数字符串合并结果
//如果拼接的字符为空,直接退出
if (str.isEmpty()) {
return this;
}
//编码格式一样
if (coder() == str.coder()) {
//将两个字符串转数组
byte[] val = this.value;
byte[] oval = str.value;
//求拼接后长度和
int len = val.length + oval.length;
//将第一数组copy进去
byte[] buf = Arrays.copyOf(val, len);
//将第二个数组copy进去
System.arraycopy(oval, 0, buf, val.length, oval.length);
//通过数组返回新的字符串
return new String(buf, coder);
}
谢谢观看!