- 在 Java 6以及之前的版本中,String对象是对char数组进行了封装实现的对象
- 主要四个成员变量:char数组、偏移量offset、字符数量count、哈希值hash
- String对象通过offset和count两个属性来定位char数组,获取字符串
- 这样可以高效快速地共享数组对象,同时节省内存空间,但也有可能会导致 内存泄露
- Java 7/8,String类中不再有offset和count两个变量
- 这样String对象占用的内存稍微少了一点
- 另外,String.substring不再共享char[],从而解决了使用该方法可能导致的内存泄露问题
- 从Java 9开始,将char[]修改为byte[],同时维护了一个新的属性coder,它是一个 编码格式 的标识
- 一个char字符占用16位,2个字节,用一个char去存储 单字节编码 的字符会非常浪费
- Java 9的String类为了节约内存空间,使用了占用8位,1个字节的byte数组来存放字符串
- coder的作用:使用length()或者indexOf()
- coder有两个默认值:0代表LATIN1,1代表UTF16
不可变性
- String是final类,char[]也是被private final修饰,这样实现了String对象的 不可变性
- 好处
- 保证了String对象的 安全性
- 保证了 hash属性不会频繁变更 ,确保了唯一性,使得HashMap等容器得以实现相应的Key-Value缓存功能
- 可以实现 字符串常量池
创建字符串对象
字面值
-
String s = "abc";
- JVM首先会检查该对象是否在字符串常量池中,如果在,就返回该对象引用,否则新的字符串将在常量池中被创建
- 这种方式可以减少同一个值的字符串对象被重复创建, 节约内存
new
-
String s = new String("abc");
- 首先,在 编译 类文件时,
"abc"
常量字符串将会放入到 常量结构 中,在 类加载 时,"abc"
将会在 常量池 中创建 - 其次,在调用new时,JVM会调用String的构造函数,同时将引用常量池中的
"abc"
字符串,在 堆内存 中创建一个String对象 - 最后,s将引用刚刚创建的String对象
优化
拼接
-
String s = "ab" + "cd" + "ef";
- 编译器优化:
String s = "ab" + "cd" + "ef";
- 编译器优化:
-
String s = "abcdef"; for ( int i = 0; i < 1000 ; i++ ) { str = str + i; }
- 编译器优化:采用 StringBuilder 进行字符串拼接
- 但每次循环都会生成一个新的StringBuilder实例,同样也会降低系统性能
- 因此做字符串拼接时,最好 显式 使用StringBuilder
intern
- 在 字符串常量 中,默认会将对象放入到 常量池 中
- 在 字符串变量 中,对象是会创建在 堆内存 中,同时也会在 常量池 中创建一个字符串对象
- 并将常量池中字符串对象的char[]引用赋值给堆内存对象中,并返回堆内存对象引用
- 如果调用intern方法,会去查看字符串常量池中是否有等于该对象的字符串
- 如果没有,就在常量池中新增该对象,并返回该对象引用
- 如果有,就返回常量池中的字符串对象引用
- 而堆内存中原有的对象由于没有引用指向它,将会被回收掉
- 常量池的实现类似于一个 HashTable ,存量的数据越多,遍历的时间复杂度会增加
// 1. 在类加载时,在常量池中创建一个字符串对象“abc” // 2. 创建a变量时,会在堆内存中创建一个字符串对象,该对象的char[]引用会指向常量池中的字符串对象的char[] // 在调用intern方法之后,会去常量池中查找是否有等于该字符串的对象,这里是有的,直接返回,刚创建的堆对象会被回收 // 3. 创建b变量的逻辑类似 String a = new String("abc").intern(); String b = new String("abc").intern(); System.out.println(a == b); // true
String s1 = "abc"; // 常量池 String s2 = new String("abc"); // 堆内存 String s3 = s2.intern(); // 常量池 System.out.println(s1 == s2); // false System.out.println(s2 == s3); // false System.out.println(s1 == s3); // true
split
- split使用正则表达式实现了强大的分割功能,但 正在表达式的性能非常不稳定
- 使用不恰当会引起 回溯 问题,导致CPU居高不下
- 所以应该谨慎使用split方法,可以考虑用indexOf来替代
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 查找一个字符串中最长不含重复字符的子字符串,计算该最长子字符串的长度
- 字符串、字符处理总结
- 高频算法面试题(字符串)leetcode 387. 字符串中的第一个唯一字符
- php删除字符串最后一个字符
- (三)C语言之字符串与字符串函数
- 算法笔记字符串处理问题H:编排字符串(2064)
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
啊哈C!思考快你一步
啊哈磊 / 电子工业出版社 / 2013-9 / 39.00元
这是一本非常有趣的编程启蒙书,全书从中小学生的角度来讲述,没有生涩的内容,取而代之的是生动活泼的漫画和风趣幽默的文字。并配合超萌的编程软件,从开始学习与计算机对话到自己独立制作一个游戏,由浅入深地讲述编程的思维。同时,与计算机展开的逻辑较量一定会让你觉得很有意思。你可以在茶余饭后阅读本书,甚至蹲在马桶上时也可以看得津津有味。编程将会改变我们的思维,教会我们如何思考,让我们的思维插上计算机的翅膀,以......一起来看看 《啊哈C!思考快你一步》 这本书的介绍吧!