源于一次bug,得知:String.contains("") 的返回值为 true
不得其解,追查了一下源代码:
# 包含关系的判断是用字符串首次出现位置实现的
# 之前没注意过,查找空字符串位置,一起看一下
public boolean contains(CharSequence s) {
# s为空字符串 indexOf返回的结果为0
return indexOf(s.toString()) > -1;
}
public int indexOf(String str) {
# 在此处,默认查找字符串的开始下标位置(第二个参数)为0
# str为空时,返回的位置为开始下标位置,逻辑详见indexOf实现方法;
return indexOf(str, 0);
}
public int indexOf(String str, int fromIndex) {
# 字符串位置查找的全部参数,分三部分:
# 1、资源字符串: 值的char数组、开始位置、长度
# 2、目标字符串: 值的char数组、开始位置、长度
# 3、开始下标
#
# 此处均资源字符、目标字符串的开始位置、查找长度进行默认;
#
# 有一个特殊的写法,String类的value属性,学习了
# 写作: private final char value[];
return indexOf(value, 0, value.length,
str.value, 0, str.value.length, fromIndex);
}
# indexOf的逻辑实现方法
static int indexOf(char[] source, int sourceOffset, int sourceCount,
char[] target, int targetOffset, int targetCount,
int fromIndex) {
if (fromIndex >= sourceCount) {
# 1、此处,当目标长度为0时,直接返回sourceCount
return (targetCount == 0 ? sourceCount : -1);
}
if (fromIndex < 0) {
fromIndex = 0;
}
# 2、此处,目标字长度为0时, 也可能返回fromIndex的值
# 结合1、2, 也就是说目标长度为0,
# 返回的数值实际上不是目标在资源中的具体位置!!!!!!
if (targetCount == 0) {
return fromIndex;
}
char first = target[targetOffset];
# 这个地方为节省循环次数,对查找的最大范围做界定
# 开始位置为sourceOffset的前提下
# 能比对的字符串最大长度 就是: sourceCount - targetCount
int max = sourceOffset + (sourceCount - targetCount);
for (int i = sourceOffset + fromIndex; i <= max; i++) {
# 查找第一个相同的char的位置
if (source[i] != first) {
while (++i <= max && source[i] != first);
}
if (i <= max) {
int j = i + 1;
int end = j + targetCount - 1;
# 按照目标长度,逐个字符进行比对
# 确定目标字符串全部都在资源字符串中
for (int k = targetOffset + 1; j < end && source[j]
== target[k]; j++, k++);
# 若长度一致 返回位置
# 此处返回的位置 是基于sourceOffset的位置
if (j == end) {
return i - sourceOffset;
}
}
}
return -1;
}
总结:
1、 contains返回true, 不一定代表包含关系, 也可能是查找的字符串为空;
以下为String.indexOf方法的总结,未对外暴漏,可以看看*********************************
2、 indexOf方法,开始下标>资源查找长度时,返回的不一定为-1(未找到), 也有肯能是 资源查找长度;
3、 indexOf方法,开始下标<=资源查找长度, 且目标长度为0时,返回的是开始下标位置;
4、 indexOf方法,返回的位置是基于sourceOffset的值,也就是说,返回值为0不一定代表目标字符串在字符串的开头;
本文深入探讨了Java中String类的contains()和indexOf()方法的内部实现,揭示了它们在处理空字符串时的特殊逻辑。当调用contains()时,返回值为true并不一定表示字符串中包含内容,可能是因为空字符串的indexOf()返回值为0。此外,还总结了indexOf()方法在不同情况下的返回值特点,包括开始下标超出范围和目标字符串长度为0的情况。



5888

被折叠的 条评论
为什么被折叠?



