Java基础复习(DayThree):字符串基础与StringBuffer、StringBuilder源码研究

String temp = “a”;

这种方式,会先去找字符串常量池里是否有保存了同样值的字符串对象,如果有,那么直接将该对象的地址赋值给temp,如果没有,那么就在字符串常量池里申请地址然后存放,temp变量保存的是常量池里的地址

//看起来像是两个对象,实则是同一个对象

String one = “a”;

String two = “b”;

sout(one == two);

在这里插入图片描述

第二种就是使用构造方法创建

构造方法可以根据字符串或者字符数组去建立

不过,这里与第一种不同的是,创建的字符串对象是保存在堆中的,而不是字符串常量池里面

String three = new String(“a”);

如果使用字符串作为构造参数去构造的话,仍然要用到字符串常量池(因为要在字符串常量池新创建或者里面就有,才可以使用),如果使用到的字符串参数不用,后面会被gc收集器回收。

这样设计的优点是,可以带来共享的效率

比较

字符串比较最好不要使用双等于,而是使用equal方法

双等于比较的只是引用地址,而equal方法是先比较引用地址,然后再比较里面的值

public boolean equals(Object anObject) {

//先判断应用地址,如果相等,肯定是相同对象

if (this == anObject) {

return true;

}

//如果应用地址不正确,再判断是否是String类型

if (anObject instanceof String) {

String anotherString = (String)anObject;

int n = value.length;

//遍历底层字符串底层的字符数组进行比较

//先判断底层字符数组长度是否相等,不相等也不用比了,肯定不对

if (n == anotherString.value.length){

char v1[] = value;

char v2[] = anotherString.value;

int i = 0;

//进行遍历比较

while (n-- != 0) {

//只要有一个比不上,就确认不相同

if (v1[i] != v2[i])

return false;

i++;

}

return true;

}

}

return false;

}

底层

从上面的源码可以看到,底层是一个字符数组,所以,它可以存储多字节的字符。

前面提到过,字符里面存储的是代码单元,所以底层字符串数组存的就是多个代码单元,这样就可以去表示各种字符串了。

这里要提及String.length方法,返回的是字符数组的长度,也就是代码单元的长度,所以不一定是字的个数

在这里插入图片描述

在这里插入图片描述

构建字符串


常用构建字符串的构造器有StringBuffer与StringBuilder

在这里插入图片描述

AbstractStringBuilder

我们可以看到,无论是StringBuffer或者是StringBuilder都是继承了这个类,所我们先研究这个类

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

里面共有4个属性

  • value:存储字符串的(字符串底层是字符数组,默认容量为16)

  • count:记录字符数组的长度,这样做的好处就是让返回字符数组长度的时间复杂度为1,而不用去遍历数组

  • MAX_ARRAY_SIZE:字符数组允许的最大长度,为( 2 31 − 8 2^{31}-8 231−8),从注释上就可以看到,这个变量并不是必要的,只不过是避免大数组会导致内存溢出(超出虚拟机的限制)。

下面就来看看append的源码

public AbstractStringBuilder append(String str) {

//判断是否为空

if (str == null)

//没有的话就调用这个方法,这个方法其实是返回一个NULL,然后value里面就存储了Null

return appendNull();

//记录长度

int len = str.length();

//也是判断底层数组长度是否足够,不够就要进行扩容

ensureCapacityInternal(count + len);

//调用字符串的getChars方法进行拼接

str.getChars(0, len, value, count);

count += len;

return this;

}

appendNull的实现

private AbstractStringBuilder appendNull() {

//就很简单使用一个字符数组,存储null,然后返回

int c = count;

//判断底层数组的长度是否足够,不够需要进行扩容

ensureCapacityInternal(c + 4);

final char[] value = this.value;

value[c++] = ‘n’;

value[c++] = ‘u’;

value[c++] = ‘l’;

value[c++] = ‘l’;

//记录此时底层字符数组长度

//至于这里为什么只用count = c

//看看value[]里面的是什么

//再看看c是什么吧

count = c;

return this;

}

ensureCapacityInternal的实现

private void ensureCapacityInternal(int minimumCapacity) {

// overflow-conscious code

//minimumCapacity是最小需要的底层字符数组长度

if (minimumCapacity - value.length > 0) {

//如果不够,进行复制

//不够的话,要按照规则进行扩容

//Arrays.copyof其实就是新建一个数组然后存放而已

value = Arrays.copyOf(value,

newCapacity(minimumCapacity));

}

}

newCapacity的实现(扩容的规则)

private int newCapacity(int minCapacity) {

// overflow-conscious code

//新的规则为,底层数组长度话为二进制然后左移一位,相当于扩展2倍

//然后再加2,所以新道德数组长度为原来的2倍加2

int newCapacity = (value.length << 1) + 2;

//再判断新的长度是否大于旧的长度

if (newCapacity - minCapacity < 0) {

newCapacity = minCapacity;

}

//如果新的长度不小于0(这里可能是因为超过了int类型的4个字节),

//又不大于最大底层字符数组长度(这个变量防止内存溢出)

//就返回新的长度

//如果大于最大底层数组长度,就调用hugeCapacity

return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0)

? hugeCapacity(minCapacity)
newCapacity;

}

hugeCapacity的实现:处理超大底层数组长度

private int hugeCapacity(int minCapacity) {

//如果是newCapacity <= 0,代表int类型字节不够存储,内存溢出

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
img

最后

现在正是金三银四的春招高潮,前阵子小编一直在搭建自己的网站,并整理了全套的**【一线互联网大厂Java核心面试题库+解析】:包括Java基础、异常、集合、并发编程、JVM、Spring全家桶、MyBatis、Redis、数据库、中间件MQ、Dubbo、Linux、Tomcat、ZooKeeper、Netty等等**

image
va开发知识点,真正体系化!**

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
[外链图片转存中…(img-7PKlbQV3-1711751851763)]

最后

现在正是金三银四的春招高潮,前阵子小编一直在搭建自己的网站,并整理了全套的**【一线互联网大厂Java核心面试题库+解析】:包括Java基础、异常、集合、并发编程、JVM、Spring全家桶、MyBatis、Redis、数据库、中间件MQ、Dubbo、Linux、Tomcat、ZooKeeper、Netty等等**

[外链图片转存中…(img-KGdqyQWb-1711751851763)]

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值