深入源码分析String类
String类基本情况
- 不可变类,使用了final修饰,不可被继承
- 一旦创建String对象,包含这个对象的字符序列不可被改变
- 底层使用字符数组 char value[]
- 实现类序列化接口,可序列化的
- 效率较低,其每次增删改操作都会重新创建一个新的String对象,会造成对象堆积,触发垃圾回收机制,若小范围对象生成,可能只会触发minor GC,大范围的话,就会触发full GC,影响效率
String类源码分析
private final char value[];
String类底层使用了char数组,并且该数组是final修饰的,不可改变,用于字符存储,所以String一旦创建之后,即不可被修改了。 因此所有的String对象的修改都不是在原来的对象基础上修改的,而是新建一个String对象对其修改并返回该新对象,原对象被废弃,资源浪费且性能较差。若遇到字符串将被频繁修改的情况,建议不要使用String,改用StringBuffer或StringBuilder。- 构造器,每次构造String对象,都不会直接去使用该原始对象,会进行复制对象,因为保证其final不可变
1 | public final class String //String类由final修饰,不能被继承,可序列化 |
equals方法
1 | // 重写equals方法,比较字符串的值是否相同 |
equalsIgnoreCase
1 | // 直接比较字符串,不区分大小写 |
comapareTo方法
1 | //比较两个字符串字典。比较是基于字符串中的每个字符的Unicode值 |
concat方法
1 | //连接两个字符串 |
valueOf方法
1 | //String与基本类型的包装类转换 |
substring方法
1 | public String substring(int beginIndex) { |
1 | // 传入了起始和结束角标值来截取 |
replace方法
1 | public String replace(char oldChar, char newChar) { |
String对象的地址问题,异同问题
字符串创建异同
1 | String a = "hxhaaj"; |
解析:
String a = "a"
这样的字符串创建方式,对象被创建在方法区的常量池中,并且当再次有相同值的字符串
被创建时,就会再次被引用到其他字符串对象变量上,即两个变量指向的是同一个在常量池中的字符串对象引用。JVM会在常量池中先查找有有没有一个值为”a”的对象,如果有,就会把它直接赋值给当前引用。即原来那个引用和现在这个引用指点向了同一对象,如果没有,则在常量池中再重新新创建一个”a”;
new String ("hxhaaj")
该方式创建的对象都会在堆中,并且即使值相同的对象,每new一次也会重新创建一个对象在堆中,所以肯定不相同。
编译优化
1 | String a = "ab"; |
解析直接创建的java对string的优化过程:编译优化 + 常量池。String b = “a” + “b”; 编译器将这个”a” + “b”作为常量表达式,在编译时进行优化,直接取结果”ab”。
常量表达式问题
1 | String a = "a1"; |
常量会在常量池中创建,常量池中的对象,都会进行优化,取常量池中的地址值,所以内存值相同。
String + String(这的string指的是直接量);
String + 基本类型;
变量表达式问题
1 | String a = "ab"; |