字符串相关类
-
String类
-
String相关类
- StringBuffer类
- StringBuilder类
String类
- 代表字符串
- 是一个final类不可继承
- 字符串为常量,用双引号引起来表示,创建后不可更改
- 字符内容存储在一个字符数组中value[ ]
- 两个对象用==比较时比较的时地址值
字符串不可变性
-
字面量赋值
String s1="abc";
-
字符串创建在常量池中,具有不可变性
-
当String值二次赋值时内存区域发生改变,不能使用原有内存区赋值
-
对现有字符串连接时,也需要重新指定内存区域;
-
当调用String的replace方法时修改字符或字符串时也必须重新指定内存区域
package Commonclass; public class Demo01 { public static void main(String[] args) { String s1="abc"; String s2="abc"; System.out.println(s1==s2);//两个对象比较时,比较的是地址,equals比较的是值 s1+="def"; System.out.println(s2);//输出abc则证明连接时重新划分内存区域,二次赋值同理可证 System.out.println(s1); } }
-
创建对象
-
字面量赋值(见上):存放于方法区的常量池中
-
通过new+构造器方式:地址为数据在堆空间中开辟空间
String s4="hello"; String s3=new String("hello");
-
注意
- 改变s3时,只会改变在堆中的引用地址
- 每个对象在堆中有不同的引用地址
例子:
package Commonclass; public class Demo1_3 { public static void main(String[] args) { Person p1=new Person("Tom",12); Person p2=new Person("Tom",12); System.out.println(p1.name.equals(p2.name));//true System.out.println(p1.name==p2.name);//true,用TOM量定义,都指向常量池同一地址 } }
String s=new String(“abc”);在内存中创建了几个对象?2个,一个堆中的new结构,另一个字符串常量对象
不同拼接操作的对比
package Commonclass;
public class Demo1_4 {
public static void main(String[] args) {
// TODO Auto-generated method stub
String s1 = "Hello";
String s2 = "China";
String s3="HelloChina";
String s4="Hello"+"China";
String s5=s1+"China";
String s6="Hello"+s2;
String s7=s1+s2;
String s8=(s1+s2).intern();
System.out.println(s3==s4);//true
System.out.println(s3==s5);//false
System.out.println(s3==s6);//false
System.out.println(s3==s7);//false
System.out.println(s5==s6);//false
System.out.println(s5==s7);//false
System.out.println(s6==s7);//false
System.out.println(s3==s8);//true
}
}
- 只要拼接的字符串存在着s1这种变量,拼接时就会在堆中开辟一块新空间(与new相似)
- 常量与常量拼接依旧存在常量池中,而且相同的常量只存在一个
- intern()调用该方法得到的是常量值在常量池中的地址。
面试题
package Commonclass;
public class StringTest {
String str=new String("good");
char[] ch= {'t','e','s','t'};
public void change(String str,char[] ch){
str="test ok";
ch[0]='b';
}
public static void main(String[] args) {
StringTest ex=new StringTest();
ex.change(ex.str, ex.ch);
System.out.println(ex.str);//good
System.out.println(ex.ch);//best
}
}
- 将ex的str地址赋给第一个参数后,因为字符串具有不可变性,所以执行str=“test ok”;时,是另开辟新空间,所以原来的值不变为,good
- 数组没有不可变性,所以值发生改变为best
- 引用数据类型赋的是地址,基本数据类型赋的是值。
常用方法
String相关类
可变性 | 线程安全性(效率) | 版本 | |
---|---|---|---|
String | x | 1.0 | |
StringBuffer | √ | 线程安全,效率低 | 1.5 |
StringBuilder | √ | 不安全,效率高 | 1.0 |
- 相同点:底层都是用char[]存储,都与String相关
- StringBuffer与StringBuilder的选择
- 先看问题是不是多线程问题
- 根据实际情况选用
例子:
package StringBuilder_Buffer;
public class Demo01 {
public static void main(String[] args) {
StringBuffer sb1=new StringBuffer("best");
sb1.setCharAt(0, 'm');
System.out.println(sb1);//mest
}
}
- 修改sb1时不再另外开辟内存空间,而是在原有基础上改
例2:底层原理对比
package StringBuilder_Buffer;
public class Demo01 {
public static void main(String[] args) {
String s1=new String();//new char [0];
String s2=new String("abc");//new char[]={'a','b','c'};
StringBuffer sb1=new StringBuffer(0);//new char[16]创建一长度为16的数组
sb1.append('a');//value[0]='a';
StringBuffer sb2=new StringBuffer("abc");//new char["abc".length+16];append("abc");
System.out.println(sb2.length());//扩容:添加的数据放不下了,需要扩容,创建一新数组容量为原来的2倍+2,将原有数组复制到新数组,
}
}
StringBuffuer
方法名 | |
---|---|
append() | 添加 |
delete() | 删除 |
replace() | 替换 |
insert() | 指定位置插入指定序列 |
reverse() | 逆置 |
indexOf() | 返回字符串第一次出现的的索引 |
subString() | 截取字符串 |
length() | 求字符串长度 |
charAt() | 返回指定字符位置 |
setChatAt() | 修改指定位置字符 |
toString() | 遍历 |
- 重点:增删改查,长度,遍历
StringBuilder 和 StringBuffer 非常类似,均代表可变的字符序列 , 而且提供相关功能的方法也一样