本篇讲解String字符串的原理 以及优化String的三种方式
最近开始学习Java性能调优了,我也在学习之余,写写自己学到的知识,以及一些感悟。
在这之前,大家先思考一个题目,答案在最后会给出。
String str1= "abc"; String str2= new String("abc"); String str3= str2.intern(); System.out.println(str1==str2); System.out.println(str2==str3); System.out.println(str1==str3);对于String对象,JDK的开发者们也做了大量的优化,来节省内存空间,提升String的性能。看看下图:
目前来看,企业中项目用Java7/8的比较多。
从 Java7 版本开始到 Java8 版本,Java 对 String 类做了一些改变。String 类中不再有 offset 和 count 两个变量了。
这样的好处是 String 对象占用的内存稍微少了些,同时,String.substring 方法也不再共享 char[],从而解决了使用该方法可能导致的内存泄漏问题。
另外,String 对象的不可变性,查看下String的源码,会发现在实现代码中 String 类被 final 关键字修饰了,而且变量 char 数组也被 final 修饰了。
我们知道类被 final 修饰代表该类不可继承,而 char[]被 final+private 修饰,代表了 String 对象不可被更改。Java 实现的这个特性叫作 String 对象的不可变性,即 String 对象一旦创建成功,就不能再对它进行改变。
Java 这样做的好处在哪里呢?- 第一,保证 String 对象的安全性。假设 String 对象是可变的,那么 String 对象将可能被恶意修改。- 第二,保证 hash 属性值不会频繁变更,确保了唯一性,使得类似 HashMap 容器才能实现相应的 key-value 缓存功能。- 第三,可以实现字符串常量池。在 Java 中,通常有两种创建字符串对象的方式,一种是通过字符串常量的方式创建,如 String str=“abc”;另一种是字符串变量通过 new 形式的创建,如 String str = new String(“abc”)。
当代码中使用第一种方式创建字符串对象时,JVM 首先会检查该对象是否在字符串常量池中,如果在,就返回该对象引用,否则新的字符串将在常量池中被创建。这种方式可以减少同一个值的字符串对象的重复创建,节约内存。
String str = new String(“abc”) 这种方式,首先在编译类文件时,"abc"常量字符串将会放入到常量结构中,在类加载时,“abc"将会在常量池中创建;其次,在调用 new 时,JVM 命令将会调用 String 的构造函数,同时引用常量池中的"abc” 字符串,在堆内存中创建一个 String 对象;最后,str 将引用 String 对象。
其实总结下来,就是三点
+号可以显示进行使用StringBuilder,提升系统性能,特别是动态字符串循环累加的时候,主动用StringBuilder可以节省一些时间和空间
使用 String.intern 节省内存(注意,一定要结合实际场景。因为常量池的实现是类似于一个 HashTable 的实现方式,HashTable 存储的数据越大,遍历的时间复杂度就会增加。如果数据过大,会增加整个字符串常量池的负担。) - 其实这个方法就是减少重复数据,增加引用
用 String.indexOf() 方法代替 Split() 方法,Split非常不稳定,在循环中使用的话,开支很大
下面说说前面题目的答案:
false false true下面说下原因:
1、String str1 = "abc";通过字面量的方式创建,abc存储于字符串常量池中; 2、String str2 = new String("abc"); 通过new对象的方式创建字符串对象,引用地址存放在堆内存中, abc则存放在字符串常量池中;所以str1 == str2?显然是false。 3、String str3 = str2.intern(); 由于str2调用了intern()方法,会返回常量池中的数据, 地址直接指向常量池,所以str1 == str3; 而str2和str3地址值不等所以也是false (str2指向堆空间,str3直接指向字符串常量池)。本节非常基础,但是千里之堤,溃于蚁穴。
日常编程中,我们往往可能就是对于一些很小的点,使用不够恰当,从而引发性能瓶颈,造成雪崩,发生线上事故。
还记得以前做对账时,因为使用正则表达式对字符串进行了匹配,引发了并发瓶颈,但是所幸没有发生事故,只是对账慢了一点,后面也优化了很多,从半小时优化到2分钟完成千万级数据的对账。
在下节日记将讲解正则表达式的相关优化内容
欢迎转载。转载请务必注明以下信息。原作者:谙忆此处原文链接有误,影响不大:https://copyfuture.com/blogs-details/20200616210314636ovbzcwcg5tzkrlc
更多精彩内容、活动、程序猿的小故事,欢迎扫码关注公众号
