共同学习Java源码--常用数据类型--String(一)

  首先来看String类,这是Java开发者最常用的一个类,也是最常用的引用类型。

  先来看String类的修饰符和实现的接口:

  

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {


  final修饰符修饰String类这个很多人都知道了,原因是什么也无需我多言。String类实现了Serializable接口,使得字符串对象可以进行序列化操作;实现了Comparable接口,使得字符串可以排序;实现了CharSequence接口,说明String类是由char数组构成,这个接口还提供了一些重要方法,比如length方法、charAt方法、subSequence方法和toString方法。

  String类成员变量中有一个char数组,来表示String的"值",这种写法很明显表明这段代码的作者是个多年经验的C程序员,C语言里字符串用char数组表示,而且[]在变量名的后面。

private final char value[];
 String类的成员变量中还有一个很有意思的东西:
<pre name="code" class="java">private static final ObjectStreamField[] serialPersistentFields =
            new ObjectStreamField[0];
这个数组所在的类暂时先不考虑,这个成员变量上面的注释是这么写的:String类是序列化流协议中的一个特殊实现,一个String实例最初以TC_String格式写入到ObjectOutputStream中,String由DataOutput.writeUTF写成的,一个新的句柄生成后指向流中的String实例的所有未来引用。我查了一下,这个类是用来声明可序列化字段的类,我理解这个变量就是这个数组用来存句柄,也就是标识String实例的整数值,但是这个数组目前是final的且长度为0,估计是目前尚未开发但以后会起作用的成员变量。

 
不纠结这个了,接下来看构造方法,有很多构造方法下面逐一解释一下:
<pre name="code" class="java">public String() {
        this.value = new char[0];
}
这个无参的构造方法将value这个char数组初始化为一个长度为0的char数组,换句话说就是一个空字符串。
 
<pre name="code" class="java">public String(String original) {
        this.value = original.value;
        this.hash = original.hash;
}
这个构造方法传入一个String变量作为唯一参数,构造方法内将这个参数的value也就是char数组传给本String类对象的value,也就是实现了值的传递,接下来又传递了参数的hash值,也就是将参数的索引也传给了本对象。
<pre name="code" class="java">public String(char value[]) {
        this.value = Arrays.copyOf(value, value.length);
}
这个构造方法传入一个char数组,然后将char数组通过数组工具类的拷贝方法全部拷贝到本类的value属性,也就是只复制了值。
 
<pre name="code" class="java">public String(char value[], int offset, int count) {
        if (offset < 0) {
            throw new StringIndexOutOfBoundsException(offset);
        }
        if (count < 0) {
            throw new StringIndexOutOfBoundsException(count);
        }
        // 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);
}
这个构造方法传入三个参数,一个是char数组,一个是要复制的数组的起点下标,另一个是要复制的数组的长度。如果下标和长度都小于0,那么会出现异常。这个构造方法实现的是将从传入的char数组中的指定下标开始复制该char数组的count个元素到本对象的value中
<pre name="code" class="java">public String(int[] codePoints, int offset, int count) {
        if (offset < 0) {
            throw new StringIndexOutOfBoundsException(offset);
        }
        if (count < 0) {
            throw new StringIndexOutOfBoundsException(count);
        }
        // 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;
}
这个构造方法较长,实际上很简单就是通过传入一个int数组,这个数组里存的是ASC码,然后后两个参数和上面那个构造方法的后两个参数一样,都是取下标和长度,然后把int数组中的指定元素以ASC码的形式取出来转换成字符再拼接,举个例子:
 
<pre name="code" class="java">String s=new String(new int[]{56,57,58},0,2);
最后s的值是89,因为取的是int数组里的第1位开始后的两位,也就是将ASC码中的56、57转换为字符拼接,也就是89。
 
</pre><pre name="code" class="java">下一篇继续写String类的源码分析




 
    


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值