String中substring源码解析
2017-08-27 本文已影响55人
capo
简书:capo
转载请注明原创出处,谢谢!
今天我们来分析下JDK>lang>String中的substring方法,下面贴上代码:
/**
返回一个字符串开始索引是从 0 开始 到 endIndex - 1
这个字符串的长度是 endIndex - beginIndex
* Returns a string that is a substring of this string. The
* substring begins at the specified {@code beginIndex} and
* extends to the character at index {@code endIndex - 1}.
* Thus the length of the substring is {@code endIndex-beginIndex}.
* <p>
* Examples:
* <blockquote><pre>
* "hamburger".substring(4, 8) returns "urge"
* "smiles".substring(1, 5) returns "mile"
* </pre></blockquote>
*
这个开始索引所在的数据包括
* @param beginIndex the beginning index, inclusive.
这个结束索引所在的数据不包括
* @param endIndex the ending index, exclusive.
* @return the specified substring.
如果这个开始索引是个负数,或者这个结束索引是个非常大的数已经超过了这个字符串的长度,或者这个开始索引已经超过了这个结束索引这3种情况都会抛出 IndexOutOfBoundsException
* @exception IndexOutOfBoundsException if the
* {@code beginIndex} is negative, or
* {@code endIndex} is larger than the length of
* this {@code String} object, or
* {@code beginIndex} is larger than
* {@code endIndex}.
*/
public String substring(int beginIndex, int endIndex) {
//开始索引 < 0 抛异常
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);
//这3个参数 依次为字符数组, 开始索引, 数组长度==
l }
再次调用数组的 Arrays.copyOfRange();方法进行复制
/**
* Allocates a new {@code String} that contains characters from a subarray
* of the character array argument. The {@code offset} argument is the
* index of the first character of the subarray and the {@code count}
* argument specifies the length of the subarray. The contents of the
* subarray are copied; subsequent modification of the character array does
* not affect the newly created string.
*
* @param value
* Array that is the source of characters
*
* @param offset
* The initial offset
*
* @param count
* The length
*
* @throws IndexOutOfBoundsException
* If the {@code offset} and {@code count} arguments index
* characters outside the bounds of the {@code value} array
*/
public String(char value[], int offset, int count) {
if (offset < 0) {
throw new StringIndexOutOfBoundsException(offset);
}
if (count <= 0) {
if (count < 0) {
throw new StringIndexOutOfBoundsException(count);
}
//如果偏移量 < 数组长度 返回 ""
if (offset <= value.length) {
this.value = "".value;
return;
}
}
// Note: offset or count might be near -1>>>1.
//如果偏移量(开始下标) > (结束索引)原来字符串长度 - 子字符串长度
if (offset > value.length - count) {
throw new StringIndexOutOfBoundsException(offset + count);
}
// 这3个参数 原始字符串 开始索引 结束索引= 初始索引+子字符串长度
this.value = Arrays.copyOfRange(value, offset, offset+count);
}
再次调用 Arrays.copyOfRange(value,offset,offset+count);方法,==第三个参数是便移量加上数组长度==
/**
复制规定了范围新的数组必须是在 0 和原始数组长度之间
* Copies the specified range of the specified array into a new array.
* The initial index of the range (<tt>from</tt>) must lie between zero
* and <tt>original.length</tt>, inclusive. The value at
* <tt>original[from]</tt> is placed into the initial element of the copy
* (unless <tt>from == original.length</tt> or <tt>from == to</tt>).
* Values from subsequent elements in the original array are placed into
* subsequent elements in the copy. The final index of the range
* (<tt>to</tt>), which must be greater than or equal to <tt>from</tt>,
* may be greater than <tt>original.length</tt>, in which case
* <tt>'\\u000'</tt> is placed in all elements of the copy whose index is
* greater than or equal to <tt>original.length - from</tt>. The length
* of the returned array will be <tt>to - from</tt>.
*
* @param original the array from which a range is to be copied
* @param from the initial index of the range to be copied, inclusive
* @param to the final index of the range to be copied, exclusive.
* (This index may lie outside the array.)
* @return a new array containing the specified range from the original array,
* truncated or padded with null characters to obtain the required length
* @throws ArrayIndexOutOfBoundsException if {@code from < 0}
* or {@code from > original.length}
* @throws IllegalArgumentException if <tt>from > to</tt>
* @throws NullPointerException if <tt>original</tt> is null
* @since 1.6
*/
public static char[] copyOfRange(char[] original, int from, int to) {
//得到新的数组长度是 = 结束索引 - 开始索引
int newLength = to - from;
if (newLength < 0)
throw new IllegalArgumentException(from + " > " + to);
char[] copy = new char[newLength];
//数组复制的几个参数依次: 原始数组,开始索引,要复制的数组,0 ,原始数组长度 - 新数组长度 求最小值
System.arraycopy(original, from, copy, 0,
Math.min(original.length - from, newLength));
return copy;
}
总结一下:
- substring(beginIndex,endIndex) 它返回的是一个下标从0开始到结束下标-1 的子字符串
- 这个字符串的长度是 length = endIndex - beingIndex
- 其内部实现就是首先调用 Arrays.copyOfRange(value,offset,offset+count),注意第三个参数是结束索引 = 开始索引 + 子字符串的长度计算得到的
- 最后调用底层的 System.arraycopy(original, from, copy, 0,
Math.min(original.length - from, newLength));
新的数组规定了必须是一个从0到原始数组长度之间
Math.min(original.length - from, newLength)取的是根据原始数组-开始索引和新的数组中取一个小的值来当结束索引