专栏首页洁癖是一只狗性能优化-字符串(String)

性能优化-字符串(String)

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

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

本文分享自微信公众号 - 洁癖是一只狗(rookie-dog),作者:洁癖汪

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-10-09

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Zookeeper基础篇---面试Paxos算法

    Paxos算法是一种基于消息传递的具有高容错性的一致性算法,Paxos算法是一种公认的晦涩难懂的算法,并且实现它有很大难度。比较有名的工程是实现有Google ...

    小土豆Yuki
  • RESTful 原来是这个意思呀

    超文本传输协议(英语:HyperText Transfer Protocol,缩写:HTTP)是一种用于分布式、协作式和超媒体信息系统的应用层协议[1]。HTT...

    小土豆Yuki
  • 面试java内存模型

    今天我们讲一下java内存模型(JMM),JMM的问题在面试中经常被问到,我们今天就讲一下这道题.

    小土豆Yuki
  • 【JAVA零基础入门系列】Day6 Java字符串

      字符串,是我们最常用的类型,每个用双引号来表示的串都是一个字符串。Java中的字符串是一个预定义的类,跟C++ 一样叫String,而不是Char数组。至于...

    弗兰克的猫
  • 字符串优化处理

    原文:https://www.relaxheart.cn/to/master/blog?uuid=87

    七七分享
  • 怒肝一夜,关于Java字符串的全部,都在这份手册里了

    String 可以说是 Java 中最常见的数据类型,用来表示一串文本,它的使用频率非常高,为了小伙伴们着想,我怒肝了一周,把字符串能写的全都写了出来。

    沉默王二
  • Python String 方法详解三:字符串的联合与分割

    返回指定长度的字符串,字符串内容居左(右)如果长度小于字符串长度,则返回原始字符串,默认填充为 ASCII 空格,可指定填充的字符串。

    软测小生
  • python学习之字符串常用方法和格式化

    Python中的字符串同样适用标准的序列操作(索引,分片,乘法,成员判断,求长度,取最小值和最大值),但因为字符串是不可变的,因此字符串不支持分片赋值。

    py3study
  • 你应该这个姿势学习PHP(1)

    1、addslashes addslasehes($string) 对字符串进行编译转义 应用场景:能防止sql的注入(当然并不完全是可以,我们可以使用pdo...

    思梦php
  • 你应该这个姿势学习PHP(1)

      应用场景:能防止sql的注入(当然并不完全是可以,我们可以使用pdo进行预处理然后方式sql的注入,安全不能只靠一种方式防止事情的发生)

    思梦php

扫码关注云+社区

领取腾讯云代金券