String类的源码--成员变量和常用的构造函数

Java中的String类非常重要,结合网上的资料以及自己分析String类的源码,做如下总结:

String类对象是不可变的,它可以被共享。

1.String类开始是这样定义的:

public final class String implements java.io.Serializable,Comparable<String>,CharSequence
从以上定义可以看出,String类实现了三个接口,且分别要实现他们的方法。

2.定义了如下成员变量:

private final char value[];
private int hash;
private static final long serialVersionUID =-6849794470754667710L;
private static final ObjectStreamField[] serialPersistentFields =
        new ObjectStreamField[0];
可以看出,String底层还是用数组来存储数据的,hash值是当使用了hashTable或者hashMap数据结构时,才会使用。后面两个变量是关于序列化的。
3.定义了如下构造方法:

(1)使用无参构造函数

public String(){
    this.value = "".value;
}
代表空字符序列,使用这个构造函数是不必要的,因为字符串对象是不可变的。这个默认的空字符串会一直存在内存中。

(2)使用字符串对象来初始化

 public String(String original) {
        this.value = original.value;
        this.hash = original.hash;
    }
新创建的实例与形参的实例中的value和hash值是相同的,说明两个value都指向了同一块内存中的数据(数组的数据)。随后修改字符串会影响原来的值。

(3)使用了数组对象来初始化

public String(char value[]) {
        this.value = Arrays.copyOf(value, value.length);
    }
Arrays.copyOf()方法中会在堆中重新申请一块内存,然后将形参中value的值复制到该新的内存中,并且将这个地址值返回给当前对象的value。形参数组的后续修改不会影响该对象的改变。
(4)截取源字符数组中的部分子字符数组来初始化
  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)截取整型数组中的部分子数组来初始化
 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;
    }
分配一个新的数组, 其中包含一个子阵列中的字符 Unicode代码点, 数组的后续修改不会影响所创建的字符串对象。

(6)使用StringBuffer对象来初始化

public String(StringBuffer buffer) {
        synchronized(buffer) {
            this.value = Arrays.copyOf(buffer.getValue(), buffer.length());
        }
 }
StringBuffer是线程安全的,所以需要加synchronized。这个用的是Arrays.copyOf()方法,分配新的空间,将buffer的序列值赋值给新空间中。说明后续数组的改变不影响新创建的字符串对象。

(7)使用StringBuilder对象来初始化

  public String(StringBuilder builder) {
        this.value = Arrays.copyOf(builder.getValue(), builder.length());
    }
StringBuilder是线程不安全的。

(8)用字符数组初始化

 String(char[] value, boolean share) {
        // assert share : "unshared not supported";
        this.value = value;
  }
  包私有构造函数。这个构造函数总是被预期用share == true调用。需要一个单独的构造函数,因为我们已经有一个public了。
    


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值