1、String定义

你所不知道的String(String系列一)


>通过源码,String是由final修饰的,不能被继承,实现序列化,其中序列化的标识是由定义的变量处理,serialVersionUID和serialPersistentFields。其中另外两个变量是char数组和hash。

![](https://s4.51cto.com/images/blog/201804/03/2f2f3120638ef0b84fcb77fc6bc4e4bd.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)

### 2、String 构造函数
>String的构造方法,一共是15个,
>8个是字节数组参数(大部分实现是由StringCoding.decode()实现),
>1个是int数组(  分配一个新的 String,它包含 Unicode 代码点数组参数一个子数组的字符),
>
>1个无参,1个原始,
>1个Stringbuffer ,1个Stringbuilder,两者都是通过Arrays.copyOf()实现,其中buffer是使用synchronized(buffer)加锁
>2个char数组(通过Arrays.copyOf()实现)。

### 3、 String的基本方法
>1个本地方法,

 public native String intern();
>15个静态公共方法包含

copyValueOf(char[]), valueOf(),format(String, Object...),join()

>50个常用公共方法;
>重点是排序算法compareTo()、hash算法( h = 31 * h + val[i];)

```
public int hashCode() {
        int h = hash;
        if (h == 0 && value.length > 0) {
            char val[] = value;

            for (int i = 0; i < value.length; i++) {
                h = 31 * h + val[i];
            }
            hash = h;
        }
        return h;
    }
```

>s[i] 是string的第i个字符,n是String的长度。那为什么这里用31,而不是其它数呢?《Effective Java》是这样说的:之所以选择31,是因为它是个奇素数,如果乘数是偶数,并且乘法溢出的话,信息就会丢失,因为与2相乘等价于移位运算。使用素数的 好处并不是很明显,但是习惯上都使用素数来计算散列结果。31有个很好的特性,就是用移位和减法来代替乘法,可以得到更好的性能:31*i==(i<<5)-i。现在的VM可以自动完成这种优化。

```

public int compareTo(String anotherString) {
        int len1 = value.length;
        int len2 = anotherString.value.length;
        int lim = Math.min(len1, len2);
        char v1[] = value;
        char v2[] = anotherString.value;

        int k = 0;
        while (k < lim) {
            char c1 = v1[k];
            char c2 = v2[k];
            if (c1 != c2) {
                return c1 - c2;
            }
            k++;
        }
        return len1 - len2;
    }
```
> 首先取出两个字符串的长度,比较较小的长度内,两者是否相等。
若不相等,则直接返回该位置字符的ASCII码相减后的值。
  若各位置都相等,则将两个字符串长度的差值返回