前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >jvm源码解析(一)String

jvm源码解析(一)String

作者头像
JathonKatu
发布2020-10-27 14:37:26
4470
发布2020-10-27 14:37:26
举报
文章被收录于专栏:JathonKatu

String底层由char数组组成

jdk1.7后,永久代被元空间替换,字符串常量池从方法区移动到java堆中

重要方法如下:

一、多构造方法

1.以String为参数的构造方法

2.以char数组为参数的构造方法

3.以StringBuffer为参数的构造方法

4.以StringBuilder为参数的构造方法

5.byte数组和int数组为参数的构造方法

二、equals方法(接收object类型的参数,返回boolean)

1.直接对比内存地址

2.对比equals里的参数是不是String类型(instanceof String)

3.对比字符串长度

4.循环对比char数组

(扩展,equalsIgnoreCaseequalsIgnoreCase,先是对比地址,然后对比长度,最后全转大写循环校验)

三、compareTo(接受String类型,返回int类型)

返回值为int类型(正数,负数,0)

循环对比char数组相同索引的值(length为两者间短的),遇到不同的char时返回char与char的差

返回length-lenght

(扩展,compareToIgnoreCase,循环(length为两者间短的)对比同索引char的值,如果不同则转成大写,如果不同则转成小写,如果不同则返回相减值,如果循环完了还没返回就返回长度差)

当equals返回true或compareTo返回0时表示字符串完全相等。

四、常用方法

indexOf(查询字符串首次出现下标位置)

lastIndexOf(查询字符串最后一次出现的下标位置)

contains(查询字符串是否包含另一个字符串)

return indexOf>-1

toLowerCase(转成小写)

toUpperCase(转成大写)

大小写转换底层写了一堆的case,效率快但是可读性差(但是做底层的大部分还是追求效率)

length(查询字符串长度)

trim(去首尾空格)

trim用的是双指针法,遍历出首尾的ascii小于等于空格的(空格是32 ,小于32的都是人为不识别的字符),返回substring

replace(替换字符串中的子串)

循环找到是否存在需要替换,不存在直接返回当前字符串,存在则new char[],然后遍历替换,new String(char[])返回

split(根据输入值分割字符串,返回字符串数组)

indexOf找到分隔符,然后根据索引返回substring,放进ArrayList里,然后toArray强转成String数组

join(字符串数组转成字符串)

stra.join(strb)

底层是new StringBuilder(stra),然后用iterator迭代strb的字符数组,append(底层是System.arraycopy)

底层是循环调用StringBuilder的append

valueOf(返回非String类型的String格式)

各基本类型调用其包装类型的toString(获取对应的字符数组然后调用String的new String(char[]),boolean则是直接三目运算符写死,引用类型调用他的toString方法

toCharArray(返回字符数组)

创建一个新数组,System.arrayCopy,返回

concat(返回String+String)

底层是System.arraycopy

substring(返回子字符串)

new String(value,start,end);

五、常见问题

为什么String要用final修饰

安全、高效

1、不可变类能够缓存结果,传参时不需要考虑值是否被修改,如果是可变类,则有可能要重新拷贝一个值进行传参,在性能上有可能有损失

2、安全,系统加载的时候需要校验一些值,如果校验完了,值被修改,可能会出现系统崩溃等问题

当字符串不可变时,才可以实现字符串常量池,缓存字符串,提高运行效率。

==和equals的区别

==对于基本类型是比较值是否相等,对于引用类型则是对比引用地址是否相等

如果类没有重写equals,则是调用Object的equals,对比的是地址

String、StringBuffer、StringBuilder的区别

1、String是不可变的,字符串拼接的时候事实上是调用了StringBuilder的append。

2、StringBuilder/StringBuffer有append和insert方法,由于StringBuffer用了Synchronized,效率低,于是在jdk1.5出现了StringBuilder

String中的intern的含义

如果常量池中没有,则新建一个到常量池,然后返回对象指向常量池中。(jdk1.7以后改成常量池中存放堆中地址)

如果有,则直接返回常量池中对象地址。

String类型在jvm中如何存储,编译器对String做了哪些优化

String str1 = "java";

String str2 = new String("java");

在jvm中存储的方式截然不同jdk1.8中,str1会先访问常量池,如果有则返回,如果没有就在常量池新建并返回

而str2是直接在堆上创建一个变量,只有调用intern,才会存储在常量池中

String str1 = "ja" + "va";

String str2 = "java";

从反编译可以看到,str1被编译成了字符串"java",因此str1 == str2 是true;

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-06-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 JathonKatu 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档