前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >性能优化-字符串(String)

性能优化-字符串(String)

作者头像
小土豆Yuki
发布2020-10-23 11:16:16
6690
发布2020-10-23 11:16:16
举报
文章被收录于专栏:洁癖是一只狗洁癖是一只狗

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

Stirng对象如何实现

  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
    • 使用String str=new String("ab") 这种方式在类编译的时候,字符串在常量池创建,然后使用new String(),同时引用常量池的引用,且在堆中创建一个string对象,再把这个字符串对象引用返回给str.

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版本以后,常量池合并到了堆中,此时不会进行复制字符串,会把堆中的字符串引用添加到常量池中.

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

本文分享自 洁癖是一只狗 微信公众号,前往查看

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

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

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