java.lang.String 分析摘要:
<1>简介
<2>常量
<3>构造器方法
<4>构造器使用的私有方法
1.简介
java.lang.String类是我们最常用的类之一,String类本身就是种数据类型,所以查看String的源码是非常重要的。
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence
基本属性:final不可继承,也就是说String类不允许覆写、子类继承等操作,字符串是常量,在创建后,字符串的值就不能改变。
实现Serializable序列化接口:能够进行对文件进行序列化和反序列化操作。
实现Comparable比较接口:能够按照一定规则进行排序,这边是按照首字母自然顺序进行比较,如果相等,则依次比较下一位。
实现CharSqequence接口:实现了一些charAt(int index)、toString()等方法。
2. 常量
这里面的都是String类的一些常量。
/** The value is used for character storage. */
//字符串的字符仓库
private final char value[];
/** Cache the hash code for the string */
//缓存字符串的hash值,默认为0
private int hash; // Default to 0
/** use serialVersionUID from JDK 1.0.2 for interoperability */
//序列化数值,用于一些相互操作
private static final long serialVersionUID = -6849794470754667710L;
/**
* Class String is special cased within the Serialization Stream Protocol.
*
* A String instance is written into an ObjectOutputStream according to
* <a href="{@docRoot}/../platform/serialization/spec/output.html">
* Object Serialization Specification, Section 6.2, "Stream Elements"</a>
*/
//String字符串类在序列化协议中是特殊的。其对象序列化规范见上面注释的链接。
private static final ObjectStreamField[] serialPersistentFields =
new ObjectStreamField[0];
3.构造器方法
String的构造器有以下几种:
//<1>注意:因为字符串是不可变的,所以不需要使用该构造方法。
public String() {
this.value = "".value;
}
//<2>初始化新创建的对象,以便它表示与参数相同的字符串序列。
//换句话说,新创建的字符串是参数字符串的副本。
//除非说需要字符串参数的显示拷贝,要不然使用该构造函数是不必要的,因为字符串是不可变的。
public String(String original) {
this.value = original.value;
this.hash = original.hash;
}
//<3>用一个字符数组来初始化一个字符串
public String(char value[]) {
this.value = Arrays.copyOf(value, value.length);
}
//<4>创建一个新的字符串,它包含了字符数组的子数组中的字符。
//value: 字符数组,用于创建新字符串(包含字符数组的子数组)
//offset:偏移量,也就是数组下标。第一位为0
//count:数量,如果为0,则表示返回一个空字符串。因为复制的数量为0
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);
}
this.value = Arrays.copyOfRange(value, offset, offset+count);
}
//<5>根据所给的整数数组codePoint的子数组来创建一个字符串
//codePoint:整数数组,其中的整数是Unicode字符代表的数,如65转过为A
//offset:偏移量,值为数组的下标。既:第一个字符为0
//count:偏移的数量。为0时,因为没有偏移,返回空字符串
public String(int[] codePoints, int offset, int count) {
if (offset < 0) {
throw new StringIndexOutOfBoundsException(offset);
}
if (count <= 0) {
if (count < 0) {
throw new StringIndexOutOfBoundsException(count);
}
if (offset <= codePoints.length) {
this.value = "".value;
return;
}
}
// Note: offset or count might be near -1>>>1.
if (offset > codePoints.length - count) {
throw new StringIndexOutOfBoundsException(offset + count);
}
final int end = offset + count;
// Pass 1: Compute precise size of char[]
int n = count;
for (int i = offset; i < end; i++) {
int c = codePoints[i];
if (Character.isBmpCodePoint(c))
continue;
else if (Character.isValidCodePoint(c))
n++;
else throw new IllegalArgumentException(Integer.toString(c));
}
// Pass 2: Allocate and fill in char[]
final char[] v = new char[n];
for (int i = offset, j = 0; i < end; i++, j++) {
int c = codePoints[i];
if (Character.isBmpCodePoint(c))
v[j] = (char)c;
else
Character.toSurrogates(c, v, j++);
}
this.value = v;
}
//<6>【该方法已过时】根据byte数组来组成一个字符串的,根据偏移生成子字符串
//ascii[]:byte数组
//hibyte:因为byte是8位数,而转成String是16位。所以前8位则用hibyte来填充
//offset:偏移量,取值为数组坐标,第一位为0
//count:偏移数量,如果为偏移数量为0,则返回空字符串
@Deprecated
public String(byte ascii[], int hibyte, int offset, int count) {
checkBounds(ascii, offset, count);
char value[] = new char[count];
if (hibyte == 0) {
for (int i = count; i-- > 0;) {
value[i] = (char)(ascii[i + offset] & 0xff);
}
} else {
hibyte <<= 8;
for (int i = count; i-- > 0;) {
value[i] = (char)(hibyte | (ascii[i + offset] & 0xff));
}
}
this.value = value;
}
//<7>【该方法已过时】根据byte数组来来完全拼成一个字符串,调用的是上个构造器的方法
//asccii[]:byte数组
//hibyte:byte是8位,String是16位,前8位则用hibyte来填充
@Deprecated
public String(byte ascii[], int hibyte) {
this(ascii, hibyte, 0, ascii.length);
}
//<8>使用指定的编码对byte数组进行解码,因为有偏移量和偏移数量,得到是解码后字符串的子串
//bytes[]:byte数组,用于指定编码格式解码
//offset:第一个解码的byte[]的下标
//length:要解码的字节数
//charset:字符集
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);
}
//<9>根据特定数组和特定字符集来构建一个String对象
public String(byte bytes[], String charsetName)
throws UnsupportedEncodingException {
this(bytes, 0, bytes.length, charsetName);
}
//还有的构造器见下篇
还有的构造器见下篇
4. 构造器使用的私有方法
构造器生成String对象过程中常用的一些方法。
//对构造方法的byte数组进行偏移量以及偏移数量的长度检查
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);
}
该方法的主要作用是:对数组进行检查,查看是否超过数组长度,如果超过长度则抛异常。
本文深入解析 Java 中 String 类的关键特性,包括其不可变性、序列化能力及如何通过多种构造器创建字符串对象。
516

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



