首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

JDK源码阅读之java.lang.String

Java 语言中 String 类用来代表字符串,相信对于 String 大家都再熟悉不过的了,这里就了解下 JDK 中怎么实现 String 类的。

阅读笔记:

1、String对象的值是一个常量,一旦创建后不能被改变。正式因为其不可变,所以它是线程安全地,可以多个线程共享。

2、String 类被声明为 final,说明它不能再被继承。同时它实现了三个接口,分别为 Serializable、Comparable 和 CharSequence。其中 Serializable 接口表明其可以序列化;

3、主要属性:

/** 用于存储字符串 */

private final char value[];

/** 缓存字符串对象的哈希值,默认值为0 */

private int hash;

/**用于排序的比较器 CaseInsensitiveComparator为内部类*/

public static final Comparator CASE_INSENSITIVE_ORDER = new CaseInsensitiveComparator();

/**

* seed value used for each alternative hash calculated.

* 用于计算每个备选哈希的种子值。 没搞明白 先不管

*/

private static final int HASHING_SEED;

4、内部类 CaseInsensitiveComparator

提供排序的比较器,实现了Comparator接口和compare方法,另外一个readResolve方法用于替换反序列化时的对象。

private static class CaseInsensitiveComparator

implements Comparator, java.io.Serializable {

// use serialVersionUID from JDK 1.2.2 for interoperability

public int compare(String s1, String s2) {

int n1 = s1.length();

int n2 = s2.length();

//取二者长度最小值

int min = Math.min(n1, n2);

//以最小值为最大循环次数开启循环比较

for (int i = 0; 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) {

// No overflow because of numeric promotion

return c1 - c2;

}

}

}

}

return n1 - n2;

}

}

判断了大写的情况还判断小写的原因是:由于自然语言的变幻莫测,有两种不同的Unicode字符具有相同的大写或小写的情况

5、构造器

没有参数的构造方法直接将空字符串的 value 进行赋值

public String() {

this.value = new char[0];

}

传入 String 对象的构造方法则将该对象对应的 value 和 hash 进行赋值。

public String(String original) {

this.value = original.value;

this.hash = original.hash;

}

构造方法传入 char 数组时,将数组数据复制为字符串

public String(char value[]) {

this.value = Arrays.copyOf(value, value.length);

}

6、length() 得到字符的长度

public int length() {

return value.length;

}

7、isEmpty() 通过判断数组长度判断字符串是否为空

public boolean isEmpty() {

return value.length == 0;

}

8、 charAt(int index) 返回指定索引的char值 索引范围限制在 大于等于0小于字符串长度之间

public char charAt(int index) {

if ((index = value.length)) {

throw new StringIndexOutOfBoundsException(index);

}

return value[index];

}

9、codePointAt(int index) 获取字符串对应索引的 Unicode 代码点

public int codePointAt(int index) {

if ((index = value.length)) {

throw new StringIndexOutOfBoundsException(index);

}

return Character.codePointAtImpl(value, index, value.length);

}

10、codePointBefore(int index) 获取字符串对应索引的前一个 Unicode 代码点 实现和codePointAt一样 只是索引减一了

public int codePointBefore(int index) {

int i = index - 1;

if ((i = value.length)) {

throw new StringIndexOutOfBoundsException(index);

}

return Character.codePointBeforeImpl(value, index, 0);

}

11、codePointCount(int beginIndex, int endIndex) 用于得到指定索引范围内代码点的个数

public int codePointCount(int beginIndex, int endIndex) {

if (beginIndex value.length || beginIndex > endIndex) {

throw new IndexOutOfBoundsException();

}

return Character.codePointCountImpl(value, beginIndex, endIndex - beginIndex);

}

12、offsetByCodePoints(int index, int codePointOffset) 返回此 String 中从给定的 index 处偏移 codePointOffset 个代码点的索引

public int offsetByCodePoints(int index, int codePointOffset) {

if (index value.length) {

throw new IndexOutOfBoundsException();

}

return Character.offsetByCodePointsImpl(value, 0, value.length,

index, codePointOffset);

}

13、getChars(char dst[], int dstBegin) 用于获取字符串对象指定范围内的字符到目标 char 数组中

void getChars(char dst[], int dstBegin) {

System.arraycopy(value, 0, dst, dstBegin, value.length);

}

14、getBytes 获取字节码数组

15、equals

用于比较两字符串对象是否相等,如果引用相同则返回 true。否则判断比较对象是否为 String 类的实例,是的话转成 String 类型,接着比较编码是否相同

16、contentEquals

比较字符串之间内容是否相等

如果为 AbstractStringBuilder 实例化出来,是的话表示它为 StringBuilder 或 StringBuffer 对象。

如果为 StringBuffer 对象,说明它是线程安全的,需要做同步处理,调用nonSyncContentEquals方法。

如果为 StringBuilder 对象,它是非线程安全的,直接调用nonSyncContentEquals方法。

如果为 String 对象,则调用equals方法比较。

接下去的逻辑属于 CharSequence 对象时的逻辑。如果长度不相等直接返回 false。

17、equalsIgnoreCase 对比字符串是否相等,而且是忽略大小写。

18、compareTo/compareToIgnoreCase(忽略大小写)

按字典顺序比较两个字符串。该比较基于字符串中各个字符的 Unicode 值。按字典顺序将此 String 对象表示的字符序列与参数字符串所表示的字符序列进行比较。如果按字典顺序此 String 对象位于参数字符串之前,则比较结果为一个负整数。如果按字典顺序此 String 对象位于参数字符串之后,则比较结果为一个正整数。如果这两个字符串相等,则结果为 0;compareTo 只在方法 equals(Object) 返回 true 时才返回 0。

19、regionMatches 检测指定区域字符串是否相等

20、startsWith 检测字符串是否以某个前缀开始,并且可以指定偏移。

21、endsWith 检测是否以某个字符串结尾,间接调用startsWith方法即可实现。

22、hashCode 返回字符串对象的哈希值,如果已经有缓存了则直接返回,否则就计算哈希值。

23、indexOf 用于查找字符串中第一个出现某字符或字符串的位置

有多种方法参数比如:可传入 int 类型,也可传入 String 类型,另外还能传入开始位置

24、lastIndexOf 返回指定字符在此字符串中最后一次出现处的索引 和indexOf类似的实现

25、substring 用于获取字符串的指定子字符串。有两个方法,一个是只传入开始索引,第二个是出传入开始索引和结束索引。

26、subSequence 等同于substring 方法 只是返回的类型不一样 这个返回的是CharSequence类型

27、concat 将指定的字符串参数连接到字符串上

28、replace 用于替换字符串中指定的字符

29、split 用于切分字符串,实现中首先会判断能不能不用正则引擎,如果可以则直接切分,否则采用正则引擎切分。

30、join (A (String), B (String[]));

ps:

在指定 String 数组B的每个元素之间串联指定的分隔符 A,从而产生单个串联的字符串

string [] tmpStr=;

string join = string.join(“|“, tmpStr);

此时jn=”abc|def|ghi”;

31、toLowerCase 将字符串成转成小写、toUpperCase 将字符串成转成大写

32、trim 用于删除字符串的头尾空白符

33、toString 返回字符串 直接返回this

34、toCharArray 将字符串转成 char 数组

35、format 格式化字符串

36、valueOf 将传入的对象转成 String 对象,可传入多种类型参数

Objet 时,为空则返回”null”字符串,否则obj.toString()。

char 数组时,直接new 一个 String 对象。

boolean 时,返回”true” 或 “false”字符串。

char 时,优先尝试转成 Latin1 编码的 String 读,否则用 UTF16。

int 时,Integer.toString(i)。

long 时,Long.toString(l)。

float 时,Float.toString(f)。

double 时,Double.toString(d)。

37、 public native String intern(); 标记了 native 的本地方法

字符串对象调用intern方法会先检查池中是否已经存在该字符串的标准对象,如果存在则直接返回标准对象,如果不存在则会往池中创建标准对象并且返回该对象。

可以在有大量重复字符串的场景下使用 以用来达到优化内存的效果

ps:100w的字符串对象里面有70w重复的对象 使用这个 可以把字符串对象数量缩小到30w

String这个类可以说是我们java开发者使用得最为频繁的类之一了,源码jdk1.7版本就有3000多行非常庞大精细,本文只是粗浅的阅读笔记 大家可以跟着源码仔细研读 相信会有更大的收获

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20190210G0RMHN00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券