byte数组转string_性能优化字符串(String)

字符串日常开发中,我们经常使用,但是我们往往会忽略他的性能问题,高效的的使用字符串,可以提高整体系统的性能,我们按照下面几个方面说明

Stirng对象如何实现

987db827b5b77d3c8353f24075a866ed.png

  1. Java6及之前的版本

    String对象是对char[]封装进行实现的对象,他的数据主要有四个属性,char[],offset,count,hash,使用count和offset定位char[],获取字符串,可以共享内存空间,节省内存,但是可能引起内存泄露.

  2. Java7,Java8版本

    这个版本不在使用count和offset,这样String对象占用内存减少了一些,同时String.subString不在共享char[],从而解决了内存泄露的问题.

  3. Java9版本

    这个版本新加了两个属性,byte[],和coder,byte[]替换了之前的char[],而coder仅仅是一个编码表示

这里说明两个问题
  • Java6为什么会发生内存泄露

    因为在这个版本,subString方法会使用new string构造函数,此时会复用char[]数组,我们使用subString方法对一个超大的字符串进行截取一小部分,此时这个subString对应一直被引用,因此超大的字符串就无法进行垃圾回收,这样就会导致内存泄露

  • Java9这样为什么这个修改

    使用byte[]是为了节省内存空间,char占用2个字节,而byte占用一个字节,而使用coder是在计算字符串长度或使用indexOf时候,判断如何计算长度的,coder=0,1,0代表单字节编码latin-1,1代表UTF-16.

String为什么是不可变对象

  1. 字符串不可修改防止恶意修改

  2. hash值不可变,保证唯一性

  3. 可以实现字符串常量池

这两说明两点
  • 字符串对象创建方式

    • 直接使用String str="ab"

      这种方式首先会先看常量池是否有值,如果有直接返回引用,如果没有则创建字符串,返回引用给str

      4fdcd3ff34fb413359f4feb433750f87.png

    • 使用String str=new String("ab")

      这种方式在类编译的时候,字符串在常量池创建,然后使用new String(),同时引用常量池的引用,且在堆中创建一个string对象,再把这个字符串对象引用返回给str.

      d7697bb41e648f4d32072aedfab4b065.png

String对象的优化

  1. 创建超大字符串

    我们日常开发中经常会拼接字符串,而我们使用+号进行拼接,会不会创建过个对象,导致性能问题呢?

    String str="ab"+"cd"+"ef"

    实际上编译后的代码仅仅生产了一个对象如下

    String str="abcdef"

    那么如果我们使用字符串变量累加呢?如下

    String str = "abcdef";for(int i=0; i<1000; i++) {      str = str + i;}

    同样编译优化后如下代码

    String str = "abcdef";for(int i=0; i<1000; i++) {     str = (new StringBuilder(String.valueOf(str)))        .append(i).toString();}
    综合发现,我日常开发中,如果直接显示的使用Stringbuilder进行拼接,来提高系统的性能,如果在多线程下可以使用Stringbuffer,但是如果不考虑使用安全问题,请使用Stirngbuilder,因为Stringbuffer会有锁竞争问题。
  2. 如何使用Stirng.intern节省内存

    String a =new String("abc").intern();String b = new String("abc").intern();if(a==b) {    System.out.print("a==b");}

    运行结果如下

    a=b

         如果是字符串常量,默认会把对象放到常量池中,如果是字符串变量,会把在堆中创建,同时在常量池创建一个字符串对象,String对象char数组会引用常量池中的char数组,并返回堆内存的引用.

          但是如果使用intern,会查看常量池是否有字符串对象的引用,如果有直接返回常量池的引用.

        如果没有,在1.6版本中,会把堆中的字符串复制到常量池中,并返回字符串的引用,此时堆中没有指向他的引用,垃圾回收器回收此引用.

        如果在1.7版本以后,常量池合并到了堆中,此时不会进行复制字符串,会把堆中的字符串引用添加到常量池中.

3dea2d3eb63e689bde9504607a4338f6.png

1c49e4feb1abc511749f0df6c9ee91ed.png

果对您有一丝丝帮助,麻烦点个关注,也欢迎转发,谢谢

扫码关注 54f4b163bd9805fbea70131985697c45.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值