2.String类源码解析

1.

首先我们可以看到是final 修饰的,不能被继承,只要被创建就不能再修改,所有我们平时看似修改实际上都是重新建了一个新的字符串。然后他实现了 Serializable接口,序列化不多赘述,Comparable 允许比较(按照ASCII码比较),CharSequence 博主第一次见,博主查阅了一下这是一个可读的字符序列,说的也很抽象。博主后来琢磨了一下,可以这样理解,这个接口提供了对char字符序列的读取。


2.

这边三个成员变量:value[] 用于存储字符,hash 用于存储该sting实例的hashCode默认为SerialVersionUID序列号

3.

这里有一个普ObjectStreamField,final类型的变量,博主看了一下翻译,String 类在序列化到流中处理的时候是特殊的,这个是专门用来存放流的。

4.String 构造函数


划横线的已经不推荐使用了,这边不再赘述


第一个构造函数,没什么特殊的,实际上该构造函数并不是必须的,因为String 类是final修饰的,不可变


第二个构造函数,直接将所需的字符串传入即可


第三个构造函数,传入字符的数组,我们可以发现他的实现很有意思,他是将字符数组整个复制过去了,这样做的目的是,复制过去之后,老的数组如果变更,就不会影响到复制过去的数组


第四个构造函数,在字符数组中从offset个开始截取count个,底层实现也是复制Arrays的形式


这边也是也是一个构造函数,中间做了一次判断,博主没有看懂,有看懂的小伙可以留言,最后通过复制的形式返回


这里几个构造函数我们放一起讲,都是用指定的字节数组来构造新的String。没有指定解码格式的会使用平台默认的编码来解码,有指定的则使用指定的编码。


此构造方法是将字符串缓冲区的字符序列分配到字符串中,地城使用Arrays 复制,值得一提的是,使用了synchronized 将改字符串缓存区的内容锁住了。


该构造方法使用类似上一个方法,只是将缓冲区的变成了字符串构建器


该构造函数,多一个是否分享的参数。

5.

校验初始值和长度是否小于0,校验下标是否越界

6.

返回字符串的长度

7.

判断字符串是否为空

8.

获取字符串指定位置的字符

9.

获取指定位置的Unicode代码点 ,方法不常用

10.

获取指定位置之前的Unicode代码点 (不常用)

11.

返回两个字符串之间的Unicode代码点数量(不常用)

12.

指定Unicode代码点,进行偏移 (不常用)

13.

将字符串中的字符复制到目标字符数组中。

14.

第一个方法是使用命名的字符集将String编码为字节序列,然后存储到新的字节数组中,第二个方法是使用指定的charset 将string 编码为一个字节序列,将结果存储到新的字节数组中。第三个方法直接按照平台默认的字符集将string编码为字节序列,然后存储到行的字节数组中。

15.

比较两个字符串是否相等的方法,首先用 instanceof 判断这个字符串是不是属于String,如果是就将这个字符串对象转成字符串,然后比较两个字符串的长度,如果长度也一样那个开始遍历这个两个char数组的每一个元素,如果全部一致,则判定这两个字符串一致。

16.

这里我们放三个方法,第一个是将字符串与stringBuffer 比较,后者是将字符串与charsequence进行比较,第三个我们先别看,先看stringbuffer 从源代码可以看出它,实际上底层调用的是 第二个方法,只是将stringbuffer进行了charsequence 强转,重点关注第二个方法的源代码,首先是做了判断,它是一层一层下来的,首先如果它属于AbstractStringBuilder,进一步判断是不是StringBuffer 如果是则加锁,加锁的目的是房子在比较过程中,stringBuffer被其他线程影响,这里可以看到真正比较的是我们的截图中的第三个方法,其实很简单,先判断长度是不是一样,如果一样在将数组中的元素一个个拿出来作比较,在回到上面,如果入参只是一个String 的话,就调用我们之前的equals方法即可作出比较,再往下,如果连string都不是,就直接把他charAt一下,遍历数组一个个做比较,这里其实我们可以看到,他在做一些判断之前都是先判断长度,这个实际上也算是一个技巧,在做一些判断是现比较一下长度,如果连长度都不一样的话,就不往下做比较了,节约时间。

17.

此方法是忽略大小写比较字符串,主要涉及到regionMatches方法,看底层可以知道如果是忽略大小写,是统一转成大写进行比较的。


18.

比较字符串,需要注意的是他返回的是int类型,首先比较的是第一位的ASCII码,如果第一位相同,比较第二位,一次类推,最后返回两者的之差,值得注意的是,如果两个字符串长度不一样,这种比较方式只比到最短的位置。如果比到这个最短位置还没有必出结果,则直接将这两个字符串长度做差。

19.

忽略大小写比较,没什么特别的全部转成小写只有比较。

20.

第二张截图不多说了,调的就是第一张截图的东西,首先这个方法,是查看字符串是否以prefix 前缀开头,第二个参数是从哪个位置开始。没什么特别的,就是和前缀一个个比过去的,一旦不一致就弹出false。

21.

没什么特别的,归根结底还是调用的startsWith的方法,第二个参数把需要计算的位置算出来了

22.

计算hashcode的方法, 哈希代码计算公式:s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1],使用int算术,其中s[i]是字符串的第i个字符,n是字符串的长度,^表示取幂。(空字符串的哈希值为零)

23.


从指定位置查看要查询的int第一次出现的位置,先做了一个判断其实位置是否大于字符串最大长度,如果是则直接返回-1,这边还做了一个判断MIN_SUPPLEMENTARY_CODE_POINT,如果小于这个,则直接遍历比较,返回第一个相同的值,如果不同则调用博主截图的第三个方法,indexOfSupplementary,比较中有两个条件,必须都相同。

24.

此方法与上述方法类似,不在赘述。就是反了一下

25.

查看字符串在该字符串中第一次出现的位置,一层套一层,主要就看最后一个截图的方法,看上去漫长其实并不复杂,就是不断的循环作比较。

26.

这个是从后往前找,和上面方法一个套路,不在赘述。

27.

subString 截取字符串,归根结底还是落到String 的一个构造方法上,整个字符串进行截取。没什么特殊的,值得注意的是,如果开始位置是0,结束位置刚好是最后一个位置,那么直接返回改字符串,反之才会重新new一个,这里可能就涉及到指向内存的问题。

28.

底层还是调用的subString方法。

29.

把传进来的字符串拼接在目标字符串后面,可以看到底层是采用的还是array的copyof。

30.

replace替换方法,如果两个一样则不替换,没有new 新的而是把原来的返回回去了,

31.

基于正则的匹配。

32.

查看这个string是否包含指定的字符,实际上就会indexOf 方法

33.

通过正则查询指定的字符串,替换第一个字符串。

34.

通过正则查找,全部替换与上面方法类似。

35.

替换从字符串开始到结束,例如,在字符串“aaa”中用“b”替换“aa”将导致“ba”而不是“ab”

36.

split切割字符串,底层是使用indexOf.可以发现很多方法都依赖于indexOf方法。

37.

组合字符串:

String message = String.join("-", "Java", "is", "cool");

    // message returned is: "Java-is-cool"

这的注意的是入参的方法,楼主第二次见到这种写法,第一次是在go的语法中,没想到java也可以这样写。值得注意的是,里面用到了一个jdk8中的新类StringJoiner。拼接字符串的时候这个类性能十分突出。

38.

所有文字转小写,参数这个locale 包含了语言之类的信息,值得一提的是 可以发现里面有个scan:{} 代码块,楼主第一次见这个东西,查了一下就是一个普通的标签,和break scan 对应。可以看到底层调用的是 Character.toLowerCase()方法。此方法与后面toUpperCase 对应,后面不再赘述。

39.

去除字符串前后的空格。底层使用subString 将整个不含空格的部门截出来。

40.

toString方法返回他自己本身。

41.

将字符串转化为字符数组。,采用arraycopy的方式。

42.

字符串格式化,后面详细解释。

43.

将对象转化成string,valueOf 重载了很多方法,这边不再赘述。

44.

本质是从char数组中截取出部分字符,组成新的字符串。

45.

这个方法楼主一开始看的也是很懵,不知道有什么用,又来细线,可能是为了提高效率,从常量池取数据比从堆里面去数据要快一些。


PS:哪里不对可以在评论中指出,我都会一个个看的,觉得少东西也可以评论中提出来,我会做补充。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,384评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,845评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,148评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,640评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,731评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,712评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,703评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,473评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,915评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,227评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,384评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,063评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,706评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,302评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,531评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,321评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,248评论 2 352

推荐阅读更多精彩内容