String类是一个字符串的包装类,下面我来给大家分析一下String类的源码。
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence
可以看到String类是一个final类,不可以用来继承,Serializable接口(可序列化接口),Comparable<String>接口(泛型为String类型的比较器接口),CharSequence接口(char值的可读序列接口)。
下面是四个全局私有变量和常量:
/** 最终char类型数组 */
private final char value[];
/** hash值 */
private int hash; // Default to 0
/** 最终序列化值 */
private static final long serialVersionUID = -6849794470754667710L;
/**串行化字段数组*/
private static final ObjectStreamField[] serialPersistentFields =
new ObjectStreamField[0];
无参构造:
public String() {
this.value = "".value;
}
初始化构造函数:
public String(String original) {
this.value = original.value;
this.hash = original.hash;
}
char类型数组构造:
public String(char value[]) {
//复制value数组到this.value数组中
this.value = Arrays.copyOf(value, value.length);
}
多参数构造:
public String(char value[], int offset, int count) {
if (offset < 0) {
//如果offset小于0抛出字符串角标越界异常
throw new StringIndexOutOfBoundsException(offset);
}
if (count <= 0) {
if (count < 0) {
//如果count的值小于0抛出字符串角标越界异常
throw new StringIndexOutOfBoundsException(count);
}
if (offset <= value.length) {
//如果offset小于等于value数组的长度,this.value的值为空字符串的value值
this.value = "".value;
//返回
return;
}
}
// 如果offset的值大于value数组的长度减去总数
if (offset > value.length - count) {
// 抛出字符串角标越界异常
throw new StringIndexOutOfBoundsException(offset + count);
}
//截取角标从offset到offset+count的数组到this.value的数组
this.value = Arrays.copyOfRange(value, offset, offset+count);
}
public String(int[] codePoints, int offset, int count) {
if (offset < 0) {
//如果offset小于0抛出字符串角标越界异常
throw new StringIndexOutOfBoundsException(offset);
}
if (count <= 0) {
if (count < 0) {
//如果count小于0抛出字符串角标越界异常
throw new StringIndexOutOfBoundsException(count);
}
if (offset <= codePoints.length) {
//空字符的值赋值给this.value
this.value = "".value;
//返回
return;
}
}
// 如果offset大于codePoints的长度减去count
if (offset > codePoints.length - count) {
//抛出字符串角标越界异常
throw new StringIndexOutOfBoundsException(offset + count);
}
//最终变量 end值等于offset的值加上count的值
final int end = offset + count;
// count的值赋值给变量n
int n = count;
//循环 offset赋值给i,i小于end,i自增
for (int i = offset; i < end; i++) {
//把codePoints数组中角标为i的值赋值给int变量c
int c = codePoints[i];
//如果c字符在bmp中
if (Character.isBmpCodePoint(c))
//循环继续
continue;
//如果字符c是一个有效的Unicode值
else if (Character.isValidCodePoint(c))
//n自增
n++;
//否则抛出非法参数异常
else throw new IllegalArgumentException(Integer.toString(c));
}
// Pass 2: Allocate and fill in char[]
//new一个最终字符数组
final char[] v = new char[n];
//循环i等于offset j等于0 i小于end i自增 j自增
for (int i = offset, j = 0; i < end; i++, j++) {
//codePoints数组角标为i的值赋值给int类型变量c
int c = codePoints[i];
//如果变量c在bmp中
if (Character.isBmpCodePoint(c))
//变量c强转成char类型并且赋值给v数组中角标为j的值中
v[j] = (char)c;
else
//
Character.toSurrogates(c, v, j++);
}
this.value = v;
}
/*
*检查offset,count参数在字节数组中是否越界的工具方法
*Common private utility method used to bounds check the byte array
* and requested offset & length values used by the String(byte[],..)
* constructors.
*/
private static void checkBounds(byte[] bytes, int offset, int length) {
if (length < 0)
throw new StringIndexOutOfBoundsException(length);
if (offset < 0)
throw new StringIndexOutOfBoundsException(offset);
if (offset > bytes.length - length)
throw new StringIndexOutOfBoundsException(offset + length);
}
/**
* 通过StringCoding类的decode方法将指定的字节数组按照指定的字符集编码
* 解码为一个字符串对象
* Constructs a new {@code String} by decoding the specified subarray of
* bytes using the specified charset. The length of the new {@code String}
* is a function of the charset, and hence may not be equal to the length
* of the subarray.
*
* <p> The behavior of this constructor when the given bytes are not valid
* in the given charset is unspecified. The {@link
* java.nio.charset.CharsetDecoder} class should be used when more control
* over the decoding process is required.
*
* @param bytes
* The bytes to be decoded into characters
*
* @param offset
* The index of the first byte to decode
*
* @param length
* The number of bytes to decode
* @param charsetName
* The name of a supported {@linkplain java.nio.charset.Charset
* charset}
*
* @throws UnsupportedEncodingException
* If the named charset is not supported
*
* @throws IndexOutOfBoundsException
* If the {@code offset} and {@code length} arguments index
* characters outside the bounds of the {@code bytes} array
*
* @since JDK1.1
*/
public String(byte bytes[], int offset, int length, String charsetName)
throws UnsupportedEncodingException {
if (charsetName == null)
throw new NullPointerException("charsetName");
checkBounds(bytes, offset, length);
this.value = StringCoding.decode(charsetName, bytes, offset, length);
}
/**
* 通过StringCoding类的decode方法将指定的字节数组按照指定的字符集编码
* 解码为一个字符串对象
* Constructs a new {@code String} by decoding the specified subarray of
* bytes using the specified {@linkplain java.nio.charset.Charset charset}.
* The length of the new {@code String} is a function of the charset, and
* hence may not be equal to the length of the subarray.
*
* <p> This method always replaces malformed-input and unmappable-character
* sequences with this charset's default replacement string. The {@link
* java.nio.charset.CharsetDecoder} class should be used when more control
* over the decoding process is required.
*
* @param bytes
* The bytes to be decoded into characters
*
* @param offset
* The index of the first byte to decode
*
* @param length
* The number of bytes to decode
*
* @param charset
* The {@linkplain java.nio.charset.Charset charset} to be used to
* decode the {@code bytes}
*
* @throws IndexOutOfBoundsException
* If the {@code offset} and {@code length} arguments index
* characters outside the bounds of the {@code bytes} array
*
* @since 1.6
*/
public String(byte bytes[], int offset, int length, Charset charset) {
if (charset == null)
throw new NullPointerException("charset");
checkBounds(bytes, offset, length);
this.value = StringCoding.decode(charset, bytes, offset, length);
}
/**
* 通过StringCoding类的decode方法将指定的字节数组按照指定的字符集编码
* 解码为一个字符串对象(重载)
* Constructs a new {@code String} by decoding the specified array of bytes
* using the specified {@linkplain java.nio.charset.Charset charset}. The
* length of the new {@code String} is a function of the charset, and hence
* may not be equal to the length of the byte array.
*
* <p> The behavior of this constructor when the given bytes are not valid
* in the given charset is unspecified. The {@link
* java.nio.charset.CharsetDecoder} class should be used when more control
* over the decoding process is required.
*
* @param bytes
* The bytes to be decoded into characters
*
* @param charsetName
* The name of a supported {@linkplain java.nio.charset.Charset
* charset}
*
* @throws UnsupportedEncodingException
* If the named charset is not supported
*
* @since JDK1.1
*/
public String(byte bytes[], String charsetName)
throws UnsupportedEncodingException {
this(bytes, 0, bytes.length, charsetName);
}
/**
* 通过StringCoding类的decode方法将指定的字节数组按照指定的字符集编码
* 解码为一个字符串对象(重载)
* Constructs a new {@code String} by decoding the specified array of
* bytes using the specified {@linkplain java.nio.charset.Charset charset}.
* The length of the new {@code String} is a function of the charset, and
* hence may not be equal to the length of the byte array.
*
* <p> This method always replaces malformed-input and unmappable-character
* sequences with this charset's default replacement string. The {@link
* java.nio.charset.CharsetDecoder} class should be used when more control
* over the decoding process is required.
*
* @param bytes
* The bytes to be decoded into characters
*
* @param charset
* The {@linkplain java.nio.charset.Charset charset} to be used to
* decode the {@code bytes}
*
* @since 1.6
*/
public String(byte bytes[], Charset charset) {
this(bytes, 0, bytes.length, charset);
}
/**
* 通过StringCoding类的decode方法将指定的字节数组按照系统平台
* 的默认字符集编码解码为一个字符串对象(重载)
* Constructs a new {@code String} by decoding the specified subarray of
* bytes using the platform's default charset. The length of the new
* {@code String} is a function of the charset, and hence may not be equal
* to the length of the subarray.
*
* <p> The behavior of this constructor when the given bytes are not valid
* in the default charset is unspecified. The {@link
* java.nio.charset.CharsetDecoder} class should be used when more control
* over the decoding process is required.
*
* @param bytes
* The bytes to be decoded into characters
*
* @param offset
* The index of the first byte to decode
*
* @param length
* The number of bytes to decode
*
* @throws IndexOutOfBoundsException
* If the {@code offset} and the {@code length} arguments index
* characters outside the bounds of the {@code bytes} array
*
* @since JDK1.1
*/
public String(byte bytes[], int offset, int length) {
checkBounds(bytes, offset, length);
this.value = StringCoding.decode(bytes, offset, length);
}
/**
* 通过StringCoding类的decode方法将指定的字节数组按照系统平台
* 的默认字符集编码解码为一个字符串对象(重载)
* 这里没有指定offset,count参数,则默认会直接截取[0,length() -1]范围内的字节即
* 默认会直接将整个字节数组解码为一个新的字符串对象
* Constructs a new {@code String} by decoding the specified array of bytes
* using the platform's default charset. The length of the new {@code
* String} is a function of the charset, and hence may not be equal to the
* length of the byte array.
*
* <p> The behavior of this constructor when the given bytes are not valid
* in the default charset is unspecified. The {@link
* java.nio.charset.CharsetDecoder} class should be used when more control
* over the decoding process is required.
*
* @param bytes
* The bytes to be decoded into characters
*
* @since JDK1.1
*/
public String(byte bytes[]) {
this(bytes, 0, bytes.length);
}
/**
* 根据传入的StringBuffer对象构造一个新的String对象,内部会将StringBuffer对象
* 内的字符数组都复制到当前对象的value属性上,注意此方法是加锁的即线程安全的。
* Allocates a new string that contains the sequence of characters
* currently contained in the string buffer argument. The contents of the
* string buffer are copied; subsequent modification of the string buffer
* does not affect the newly created string.
*
* @param buffer
* A {@code StringBuffer}
*/
public String(StringBuffer buffer) {
synchronized(buffer) {
this.value = Arrays.copyOf(buffer.getValue(), buffer.length());
}
}
/**
* 根据传入的StringBuilder对象构造一个新的String对象,内部会将StringBuilder对象
* 内的字符数组都复制到当前对象的value属性上,注意此方法不是线程安全的。
* Allocates a new string that contains the sequence of characters
* currently contained in the string builder argument. The contents of the
* string builder are copied; subsequent modification of the string builder
* does not affect the newly created string.
*
* <p> This constructor is provided to ease migration to {@code
* StringBuilder}. Obtaining a string from a string builder via the {@code
* toString} method is likely to run faster and is generally preferred.
*
* @param builder
* A {@code StringBuilder}
*
* @since 1.5
*/
public String(StringBuilder builder) {
this.value = Arrays.copyOf(builder.getValue(), builder.length());
}
/*
* Package private constructor which shares value array for speed.
* this constructor is always expected to be called with share==true.
* a separate constructor is needed because we already have a public
* String(char[]) constructor that makes a copy of the given char[].
*/
String(char[] value, boolean share) {
// assert share : "unshared not supported";
this.value = value;
}
/**
* 返回一个字符串的长度,此长度必须等于Unicode编码单元的长度。
* 一个Unicode编码单元为16个bit,而一个char字符占2个字节刚好16个bit,即
* 一个字符串的长度等于它包含的字符个数。
* Returns the length of this string.
* The length is equal to the number of <a href="Character.html#unicode">Unicode
* code units</a> in the string.
*
* @return the length of the sequence of characters represented by this
* object.
*/
public int length() {
return value.length;
}
/**
* 判断一个字符串是否为一个空字符串[""]
* 当且仅当字符串的length()等于零,此方法才返回true,否则返回false
* Returns {@code true} if, and only if, {@link #length()} is {@code 0}.
*
* @return {@code true} if {@link #length()} is {@code 0}, otherwise
* {@code false}
*
* @since 1.6
*/
public boolean isEmpty() {
return value.length == 0;
}
/**
* 返回字符串某个索引位置的字符
* Returns the {@code char} value at the
* specified index. An index ranges from {@code 0} to
* {@code length() - 1}. The first {@code char} value of the sequence
* is at index {@code 0}, the next at index {@code 1},
* and so on, as for array indexing.
*
* <p>If the {@code char} value specified by the index is a
* <a href="Character.html#unicode">surrogate</a>, the surrogate
* value is returned.
*
* @param index the index of the {@code char} value.
* @return the {@code char} value at the specified index of this string.
* The first {@code char} value is at index {@code 0}.
* @exception IndexOutOfBoundsException if the {@code index}
* argument is negative or not less than the length of this
* string.
*/
public char charAt(int index) {
if ((index < 0) || (index >= value.length)) {
throw new StringIndexOutOfBoundsException(index);
}
return value[index];
}
/**
* index索引位置的字符往后偏移codePointOffset个索引位置,返回偏移后的索引位置
* Returns the index within this {@code String} that is
* offset from the given {@code index} by
* {@code codePointOffset} code points. Unpaired surrogates
* within the text range given by {@code index} and
* {@code codePointOffset} count as one code point each.
*
* @param index the index to be offset
* @param codePointOffset the offset in code points
* @return the index within this {@code String}
* @exception IndexOutOfBoundsException if {@code index}
* is negative or larger then the length of this
* {@code String}, or if {@code codePointOffset} is positive
* and the substring starting with {@code index} has fewer
* than {@code codePointOffset} code points,
* or if {@code codePointOffset} is negative and the substring
* before {@code index} has fewer than the absolute value
* of {@code codePointOffset} code points.
* @since 1