一、什么是String
String对象用于保存字符串,字符串常量对象是用双括号引起的字符序列。序列中的字符使用Unicode字符编码,一个字符无论是汉字还是字母都占两个字节。常用的构造器:
String s1 = new String();
String s2 = new String(String original);
String s3 = new String(char[] a);
String s4 = new String(char[] a,int startIndex,int count);
String s5 = new String(byte[] b);
一些细节:
- String实现了接口Serializable,这使得String可以串行化,也就是可以在网络中传输。还实现了接口Comparable,让String对象可以比较大小。
- String是final类,不能被其它类继承。
- String真正用来存放字符串内容的是一个字符数组:private final char value[]。
- value一个final类型,它指向的地址不可以修改,但是可以修改数组的内容。
二、String类创建剖析
String s = "hello world"
这中创建方式先从常量池查看是否有"hello world"的数据空间,如果有直接指向;如果没有则重新创建,然后指向。s最终指向的是常量池的空间地址。
String s2 = new String("hello world");
这种方式先在堆中创建空间,里面维护了value的属性,指向常量池的"hello world"空间,如果常量池中没有则重新创建,如果有直接通过value指向。最终指向的是堆中的空间地址。就是s2指向value,value指向常量池的空间地址。
三、String类的常见方法
equals方法:判断字符串的内容是否相等,它是区分大小写的。
String a = new String("hello");
String b = "hello";
System.out.println(a.equals(b));
equalsIgnoreCase方法:忽略大小写,判断内容是否相等。
String a = new String("HeLlo");
String b = "hello";
System.out.println(a.equalsIgnoreCase(b));
length方法:获取字符的个数,返回字符串的长度 。
String a = new String("HeLlo");
System.out.println(a.length());
indexOf方法:获取字符在字符串中第一次出现的索引,索引从0开始,如果找不到,返回-1 。
System.out.println("we are we".indexOf("we"));
lastIndexOf方法:获取最后一次出现的位置,索引从0开始,如果找不到,返回-1。
System.out.println("we are we".lastIndexOf("we"));
subtring方法:截取指定范围的子串。
//从索引0开始截取,截取到索引5之前的一个字符
System.out.println("hello,张三".substring(0,5));
//从索引6开始截取完后面所有内容
System.out.println("hello,张三".substring(5));
toUpperCase方法:将字符串的小写字母全部转换成大写。
System.out.println("Hello World".toUpperCase());
toLowerCase方法:将字符串的大写字母全部转换成小写。
System.out.println("Hello World".toLowerCase());
concat方法:拼接字符串。
String str1 = "hello ";
String str2 = "world";
String str3 = str2.concat(str1);
System.out.println(str3);//也可以这样
System.out.println("Hello ".concat("World").concat("!"));
replace方法:替换字符串中的字符,返回的结果才是替换过的,本身对str1没有影响。
String str1 = "hello ";
String str2 = str1.replace('l','k');
System.out.println(str2);
split方法:分割字符串,对于某些分割字符,需要转义才能正确使用。
String str1 = "hello world wo shi";
String[] strs = str1.split(" ");
for(String s : strs){System.out.println(s);}
toCharArray方法:将String转换为字符数组。
String str = "Hello World";
char[] chars = str.toCharArray();
for (int i = 0; i < chars.length; i++) {System.out.print(chars[i]);}
compareTo方法:比较两个字符串的大小。
- 如果长度相同,且每个字符相同,返回0。
- 如果长度相同或者不相同,但是在进行比较时,可以区分大小们就返回不相同的字符的ASCLL码值之差。
- 如果前面都相同,则返回str1.len-str2.len。
String str1 = "JACK";
String str2 = "JACL";
System.out.println(str1.compareTo(str2));//'K'-'L' = -1;String str1 = "JACK";
String str2 = "JACKLOM";
System.out.println(str1.compareTo(str2));//4 - 7 = -3
format方法: 使用占位符,%s表示字符串替换,%d表示用整数替换,%,2f表示用小数来替换。
String formatStr = "我是%s,年龄是%d,成绩是%.2f,性别是%c";
String name = "小王";
int age = 18;
float grade = 97.34f;
char gender = '男';
System.out.println(String.format(formatStr, name, age, grade, gender));
System.out.printf((formatStr) + "%n", name, age, grade, gender);
四、StringBuffer类
4.1什么是StringBuffer类
StringBuffer类的直接父类是AbstractStringBuilder,在父类中,有属性char[] value,不是final类型的。该数组存放字符串类型,存放在堆中。所以StringBuffer代表可变长度的字符序列,可以对字符串的内容进行增删。
StringBuffer也是一个final类,不可被继承。
4.2String类与StringBuffer类
- String类保存的是字符串常量,里面的值不能更改,每次String类的更新实际上是更改地址。
- StringBuffer类保存的是字符串变量,里面的值可以更改,每次StringBuffer的更新实际上可以更新内容不用不用每次都更新地址。
4.3StringBuffer类的构造器
//默认构造器,创建一个容量为16的字符缓冲区
StringBuffer s1 = new StringBuffer();//创建一个指定大小的字符串缓冲区
StringBuffer s2 = new StringBuffer(100);//创建一个指定内容的字符串缓冲区
StringBuffer s3 = new StringBuffer(String str);
4.4StringBuffer类与String类的互相转换
String——>StringBuffer
//String ->StringBuffer
//方式一,通过构造器
String str = "hello world";
//返回的是StringBuffer对象,对str本身没有影响
StringBuffer strb = new StringBuffer(str);
//方式二,使用append方法
StringBuffer strb2 = new StringBuffer();
strb2 = strb2.append(str);
StringBuffer——>String
StringBuffer strb = new StringBuffer("hello world");
//方法一,使用toString方法
String s = strb.toString();
//使用构造器来搞定
String s1 = new String(strb);
4.5StringBuffer方法
appned方法
StringBuffer strb = new StringBuffer("hello world");
strb.append(",");
System.out.println(strb);
delete方法
StringBuffer strb = new StringBuffer("hello world");
//delete(int start, int end)
//删除索引>=start && < end处的字符strb.delete(5,strb.length());
System.out.println(strb);
replace函数
StringBuffer strb = new StringBuffer("hello world");
//replace(int start, int end, String str)
//将索引在[start,end)之间的字符替换为字符串 strstrb.replace(1,2,"hello");
System.out.println(strb);
indexOf方法
StringBuffer strb = new StringBuffer("hello world");
//indexOf(String str)
//必须传递String参数,否则需要使用toString方法
//返回指定的字串在字符串中第一次出现的索引
System.out.println(strb.indexOf("l"));StringBuffer strb = new StringBuffer("hello world");
StringBuffer str1 = new StringBuffer("l");
System.out.println(strb.indexOf(str1.toString()));
insert方法
StringBuffer strb = new StringBuffer("hello world");
StringBuffer str1 = new StringBuffer("李");
//insert(index,String str)
//下面两种写法都可以
//索引为index的内容自动后移System.out.println(strb.insert(5,str1));
System.out.println(strb.insert(5,str1.toString()));
五、StringBuilder类
5.1什么是SrringBuilder类
一个可变的字符序列,这个类提供一个与StringBuffer兼容的API,但不保证同步(StringBuilder不是线程安全的),这个类被设计用作StringBuffer的一个简易替换。建议优先采用该类,因为在大多数实现中,它比StringBuffer类要快。
StringBuffer类和StringBbuilder均代表可变的字符序列,方法是一样的。StringBuilder的方法没有做互斥处理,所以在单线程的情况下使用。
5.2String、StringBuiler与StringBuffer类的比较
- StringBuilder与StringBuffer非常类似,均代表可变的字符序列,而且方法也一样
- String:不可变字符序列,效率低,但是复用率高。
- StringBuffer:可变字符序列,效率较高,线程安全。
- StringBuilder:可变字符序列,效率最高,线程不安全。
- String使用的注意说明:
- String s = 'a';创建了一个字符串,再执行s += 'b';这样的指令实际上把原来的'a'丢弃了,现在又产生了一个字符串s + "b"。如果多次执行这样改变字符串的操作,会导致大量的副本字符串对象存留在内存中。所以,如果要对String进行大量的修改,建议不适用String。
结论就是:
- 如果字符串存在大量修改操作,使用StringBuffer或者StringBuilder。
- 如果字符串存在大量的修改操作,并且在单线程的情况下,使用StringBuilder。
- 如果字符串存在大量的修改操作,并且是多线程的情况,使用StringBuffer。
- 如果我们字符串很少修改,并被多个对象引用,则使用String,比如说配置信息等。