JAVA 字符串 12 字符串相关类的底层原理

1 字符串存储的内存原理

  • 直接赋值复用字符串常量池中的内存,比较节约内存
  • new 出来不会复用,而是开辟一个新的空间

2 ==号比较的到底是什么?

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

3 字符串拼接的底层原理

3.1 没有变量参与的拼接

package com.bjpowernode;

public class Test {
    public static void main(String[] args) {
        String s = "a" + "b" + "c";
        System.out.println(s);
    }
}

拼接的时候没有变量,都是字符串
触发字符串的优化机制,
在编译的时候就已经是最终的结果了

3.2 有变量参与的拼接

package com.bjpowernode;

public class Test {
    public static void main(String[] args) {
        String s1 = "a" ;
        String s2 = s1 + "b";
        String s3 = s2 + "c";
        System.out.println(s3);
    }
}

在拼接的时候有变量

3.2.1 JDK8 以前底层会使用 StringBuilder

一个加号,堆内存中俩对象

  • String s2 = s1 + "b"; 会创建 StringBuuilder 对象 s1,和串池中的 "b" 拼接以后,在 toStriing 转成 String 对象 "ab"
  • String s3 = s2 + "c";  会创建 StringBuuilder 对象 s2,和串池中的 "c" 拼接以后,在 toStriing 转成 String 对象 "abc"

3.2.2 JDK8 以后

字符串拼接的时候有变量参与:

  • 在内存中创建了很多对象
  • 浪费空间,时间也非常慢

3.3 总结

  • 如果没有变量参与,都是字符串直接相加,编译之后就是拼接之后的结果会复用串池中的字符串
  • 如果有变量参与每一行拼接的代码,都会在内存中创建新的字符串,浪费内存。
  • 如果很多字符串变量拼接,不要直接+。在底层会创建多个对象,浪费时间,浪费性能。

4 StringBuilder提高效率原理图

4.1 面试水题

package com.bjpowernode;

public class Test {
    public static void main(String[] args) {
        String s1 = "abc" ;
        String s2 = "ab";
        String s3 = s2 + "c";
        System.out.println(s1 == s3);   
    }
}

运行结果是什么?                         false

分析:

s1 是直接赋值,所以记录的是串池中的地址值

s3 是 + 拼接操作,且有变量参与,是新 new 出来的对象

  • JDK8 以前:系统底层会自动创建一个 StringBuilder 对象,然后再调用其 append 方法完成拼接。拼接后,再调用其 toString 方法转换为 String 类型,而 toString 方法的底层是直接 new 了一个字符串对象。
  • JDK8 版本:系统会预估要字符串拼接之后的总大小,把要拼接的内容都放在数组中,此时也是产生一个新的字符串。

4.2 面试水题

package com.bjpowernode;

public class Test {
    public static void main(String[] args) {
        String s1 = "abc" ;
        String s2 = "a" + "b" + "c";
        System.out.println(s1 == s2);
    }
}

运行结果是什么?                         true

分析:

s1 是直接赋值,所以记录的是串池中的地址值

s2 是没有变量参与的拼接,所以在编译成 .class 之后,就相当于是直接赋值为 "abc",而在串池中,如果字符串已经存在,就会复用(在串池中,只有字符串不存在,才会新创建)

4.3 总结

所有要拼接的内容都会往 StringBuilder 中放,不会创建很多无用的空间,节约内存

5 StringBuilder 源码分析

StringBuilder 在刚开始创建的时候,底层会创建一个字节数组,默认的容量是 16(容量即最多能装多少,长度是指实际装了多少)

如果添加的长度超过了 16,则会扩容,默认扩容:老容量 * 2 + 2 = 34

如果超出了 *2 + 2 的容量,则会以实际需要的大小为准 

5.1 总结

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

参考链接:字符串-12-字符串相关类的底层原理_哔哩哔哩_bilibili

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值