String 是final类,不能被继承,并实现了接口如下代码

String源码jdk8

1:实现接口。

public final class String
implements java.io.Serializable, Comparable, CharSequence {}
```
####1.1 Serializable
这个序列化接口没有任何方法和域,仅用于标识序列化的语意。
####1.2 Comparable
这个接口只有一个compareTo(T 0)接口,用于对两个实例化对象比较大小。
####1.3 CharSequence
这个接口是一个只读的字符序列。包括length(), charAt(int index), subSequence(int start, int end)这几个API接口,值得一提的是,StringBuffer和StringBuild也是实现了改接口。
###2变量
```java
//value[]是存储String的内容的,即当使用String str = "abc";的时候,本质上,"abc"是存储在一个char类型的数组中的。
private final char value[];
//hash是String实例化的hashcode的一个缓存。因为String经常被用于比较,比如在HashMap中。如果每次进行比较都重新计算hashcode的值的话,那无疑是比较麻烦的,而保存一个hashcode的缓存无疑能优化这样的操作。默认值为0
private int hash;
//这个CASE_INSENSITIVE_ORDER在下面内部类中会说到,其根本就是持有一个静态内部类,用于忽略大小写得比较两个字符串。
public static final Comparator CASE_INSENSITIVE_ORDER
= new CaseInsensitiveComparator();

3.内部类。

private static class CaseInsensitiveComparator
implements Comparator, java.io.Serializable {
private static final long serialVersionUID = 8575799808933029326L;
//不区分大小写比较
public int compare(String s1, String s2) {
//获取s1和s2的长度
int n1 = s1.length();
int n2 = s2.length();
//min为n1和n2的较小值
int min = Math.min(n1, n2);
//按照字符串长度短的遍历
for (int i = 0; i < min; i++) {
char c1 = s1.charAt(i);
char c2 = s2.charAt(i);
if (c1 != c2) {
//转换成大写字母
c1 = Character.toUpperCase(c1);
c2 = Character.toUpperCase(c2);
if (c1 != c2) {
//转成小写字母
c1 = Character.toLowerCase(c1);
c2 = Character.toLowerCase(c2);
if (c1 != c2) {
//小于0 说明s1
//大于0 说明s1>s2
return c1 - c2;
}
}
}
}
//执行到这里说明字符串短的已经执行到结尾了
//那接下来就比较谁的字符串长度长了
//小于0 说明s1
//大于0 说明s1>s2
//等于0 说明s1==s2
return n1 - n2;
}
private Object readResolve() { return CASE_INSENSITIVE_ORDER; }
}
String类中的方法
// 不区分大小写比较字符串
public int compareTo(String anotherString) {
// 字符串存储在数组value中,
//value数组的长度就是字符串的长度
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) {
//小于0 说明当前对象字符串长度
//大于0 说明当前对象字符串长度>anotherString
return c1 - c2;
}
k++;
}
//执行到这里说明字符串短的已经执行到结尾了
//那接下来就比较谁的字符串长度长了
//小于0 说明当前对象字符串长度
//大于0 说明当前对象字符串长度>anotherString
//等于0 说明当前对象字符串长度
return len1 - len2;
}
//忽略字符大小写比较字符串的大小
public int compareToIgnoreCase(String str) {
return CASE_INSENSITIVE_ORDER.compare(this, str);
}

这里有一个疑惑,在String中已经有了一个compareTo的方法,为什么还要有一个CaseInsensitiveComparator的内部静态类呢?

其实这一切都是为了代码复用。

首先看一下这个类就会发现,其实这个比较和compareTo方法也是有差别的,这个方法在比较时是忽略大小写的。

而且这是一个单例,可以简单得用它来比较两个String,因为String类提供一个变量:CASE_INSENSITIVE_ORDER 来持有这个内部类,这样当要比较两个String时可以通过这个变量来调用。

其次,可以看到String类中提供的compareToIgnoreCase方法其实就是调用这个内部类里面的方法实现的。这就是代码复用的一个例子。

4:方法。

String构造方法,支持多种初始化方法,包括接收String,char[],byte[],StringBuffer等多种参数类型的初始化方法。但本质上,其实就是将接收到的参数传递给全局变量value[]。

public int length() {
//字符串长度即数组value的长度
return value.length;
}
public boolean isEmpty() {
//数组长度为0则说明字符串是否为空
return value.length == 0;
}
//返回索引位置的字符
public char charAt(int index) {
//判断索引是否越界
if ((index < 0) || (index >= value.length)) {
//越界抛出异常
throw new StringIndexOutOfBoundsException(index);
}
//返回索引位置的字符
return value[index];
}

知道了String其实内部是通过char[]实现的,那么就不难发现length(),isEmpty(),charAt()这些方法其实就是在内部调用数组的方法。