String:字符串
1、String的特性
- 字符串是常量,创建后不可改变
- 字符串字面值存储在字符串常量池中,可以共享,详情见下方代码分析
字符串常量池分析
package com.qianfeng.xqc.day0303;
public class DemoString {
public static void main(String[] args) {
String st1 = "abc";
String st2 = "abc";
System.out.println("st1 = st2 : " + (st1 == st2));
// st1 == st2;
**使用字符串常量池,每当我们使用字面量(String s=”1”;)创建字符串常量时,JVM会首先检查字符串常量池,如果该字符串已经存在常量池中,那么就将此字符串对象的地址赋值给引用s(引用s在Java栈中)。如果字符串不存在常量池中,就会实例化该字符串并且将其放到常量池中,并将此字符串对象的地址赋值给引用s(引用s在Java栈中)。
// 这一句代码创建了2个对象;
// "abc" : 存储在字符串常量池中
// new String() : 存储在堆
String ssr1 = new String("abc");
// "abc" : 存储在字符串常量池中,可以共享;所以下面这一句代码,将会创建1个对象
String ssr2 = new String("abc");
System.out.println("ssr1 = ssr2 : " + (ssr1 == ssr2));
// ssr1 == ssr2;
**使用字符串常量池,每当我们使用关键字new(String s=new String(”1”);)创建字符串常量时,JVM会首先检查字符串常量池,如果该字符串已经存在常量池中,那么不再在字符串常量池创建该字符串对象,而直接堆中复制该对象的副本,然后将堆中对象的地址赋值给引用s,如果字符串不存在常量池中,就会实例化该字符串并且将其放到常量池中,然后在堆中复制该对象的副本,然后将堆中对象的地址赋值给引用s。
String str1 = "ab" + "cd"; // 1个对象
String str11 = "abcd";
System.out.println("str1 = str11 : " + (str1 == str11)); // true
/**
* 情景四:
局部变量str2,str3存储的是存储两个拘留字符串对象(intern字符串对象)的地址。
第三行代码原理(str2+str3):
运行期JVM首先会在堆中创建一个StringBuilder类,
同时用str2指向的拘留字符串对象完成初始化,
然后调用append方法完成对str3所指向的拘留字符串的合并,
接着调用StringBuilder的toString()方法在堆中创建一个String对象,
最后将刚生成的String对象的堆地址存放在局部变量str3中。
而str5存储的是字符串池中"abcd"所对应的拘留字符串对象的地址。
str4与str5地址当然不一样了
内存中实际上有五个字符串对象:
三个拘留字符串对象、一个String对象和一个StringBuilder对象。
*/
String str2 = "ab"; // 1个对象
String str3 = "cd"; // 1个对象
String str4 = str2 + str3;
String str5 = "abcd";
System.out.println("str4 = str5 : " + (str4 == str5)); // false
String str6 = "b";
String str7 = "a" + str6;
String str67 = "ab";
System.out.println("str7 = str67 : " + (str7 == str67));
// ↑str6为变量,在运行期才会被解析。
final String str8 = "b";
String str9 = "a" + str8;
String str89 = "ab";
System.out.println("str9 = str89 : " + (str9 == str89));
// ↑str8为常量变量,编译期会被优化
}
}
2、常用方法
3、 StringBuffer和StringBuilder
StringBuffer是线程安全的.
StringBuffer又称为可变字符序列,它是一个类似于 String 的字符串缓冲区,通过某些方法调用可以改变该序列的长度和内容。原来StringBuffer是个字符串的缓冲区,即就是它是一个容器,容器中可以装很多字符串。并且能够对其中的字符串进行各种操作。
StringBuilder是线程不安全的.
StringBuilder类在 Java 5 中被提出,它和StringBuffer之间的最大不同在于 StringBuilder的方法不是线程安全的(不能同步访问)
由于StringBuilder 相较于StringBuffer 有速度优势,所以多数情况下建议使用StringBuilder 类。然而在应用程序要求线程安全的情况下,则必须使用StringBuffer 类。
序号 | 方法描述 |
---|---|
1 | public StringBuffer append(String s) 将指定的字符串追加到此字符序列。 |
2 | public StringBuffer reverse() 将此字符序列用其反转形式取代。 |
3 | public delete(int start, int end) 移除此序列的子字符串中的字符。 |
4 | public insert(int offset, int i) 将 int 参数的字符串表示形式插入此序列中。 |
5 | replace(int start, int end, String str) 使用给定 String 中的字符替换此序列的子字符串中的字符。 |