java基础学习 day36(字符串相关类的底层原理)

1. 字符串存储的内存原理

  • 直接赋值会复用字符串常量池中已有的
  • new出来的不会复用,而是开辟一个新的空间来创建

2. “==”号比较的到底是什么

  • 基本数据类型比较数据值
  • 引用数据类型比较地址值

PS. 所以以后对引用数据类型,不要用“==”,改用.equals()方法

3. 字符串拼接的底层原理

  • 拼接的时候没有变量,都是字符串,会触发字符串的优化机制,在编译的时候(将.java文件编译为.class文件)就已经是最终的结果了,在执行运行代码(用java命令运行)的时候,也就是运行的最终结果了,即 “a”+“b”+“c”和“abc” 一样,也就是会复用串池中的字符串(若已有“abc”,则“a”+“b”+“c”不会创建新的字符串,而是直接复用“abc”),如图:
    在这里插入图片描述

  • 拼接的时候有变量参与,在JDK8以前,底层会用StringBuilder,以及它的.append()方法来进行拼接,最后用.toString()方法变回字符串,过程如图:
    在这里插入图片描述
    PS. 有变量参与,会先在堆中new一个StringBuilder对象,而toString()方法返回的字符串也是new出来的,所以也会在堆内存中开辟一块新空间来存放返回的字符串。综上,一个“+”,会创建两个对象。

  • 拼接时有变量参与,从JDK8开始,会先预估拼接后字符串的长度,并创建对应长度的数组,同时,往数组中存入数据,最后把这个数组整体变回字符串,也是new出来的,不受串池管理,如图:
    在这里插入图片描述
    PS. 预估,和创建数组,在创建返回的字符串也需要较多时间,需要较多内存

  • 综上:如果很多字符串变量拼接,不要直接“+”。在底层会创建多个对象,浪费时间,浪费性能。改为采用StringBuilder或StringJoiner来拼接。

4. StringBuilder提高效率的原理图
在这里插入图片描述

  • 若.append(添加的内容)中,添加的内容为字符串,则会在串池中创建对应的字符串,若已有则复用,不会直接new。

5. StringBuilder的源码分析

  • 默认创建一个长度为16的字节数组,添加的内容(每一位字符都转换为对应的ASCII码)长度小于16,直接存,添加的内容长度大于16会扩容(原来的容量*2+2),如果扩容之后还不够,就以实际长度为准

猜你喜欢

转载自blog.csdn.net/u011453680/article/details/128730492