Java中的字符采用Unicode编码。Java SE提供了三个字符串类:String,StringBuffer,StringBuilder。String是不可变字符串,StringBuffer和StringBuilder是可变字符串。
1.不可变字符串String
很多计算机语言都提供了两种字符串,即不可变字符串和可变字符串,它们的区别在于当字符串进行拼接等修改操作时,不可变字符串会创建新的字符串对象,而可变字符串不会创建新对象。
Java中不可变字符串类是String,属于java.lang包。在使用java.lang包中的类时不需要引入(import)该包,因为它是由解释器自动引入的。
1.1创建字符串对象
public class stringCreate {
public static void main(String[] args) {
//创建字符串对象
String s1=new String();
String s2=new String("Hello World");
System.out.println("s1="+s1);
System.out.println("s2="+s2);
char chars[]= {'a','b','c','d','e'};
//通过字符数组创建
String s3=new String(chars);
//通过子字符数组创建字符串对象
String s4=new String(chars,1,4); //1是数组第一个字符的索引,4是指定子数组的长度
System.out.println("s3="+s3);
System.out.println("s4="+s4);
byte bytes[]= {97,98,99};
//通过byte数组创建字符串对象
String s5=new String(bytes);
System.out.println("s5="+s5);
System.out.println("s5字符串长度="+s5.length());
}
}
运行结果:
1.2字符串池
public class stringCreate {
public static void main(String[] args) {
String s6=new String("Hello"); //使用new关键字创建
String s7=new String("Hello");
String s8="Hello"; //字符串常量
String s9="Hello";
System.out.printf("s6==s7:%b\n",s6==s7);
System.out.printf("s8==s9:%b\n",s8==s9);
System.out.printf("s6==s8:%b\n",s6==s8);
System.out.printf("s7==s8:%b\n",s7==s8);
}
}
运行结果:
==比较的是两个引用是否指向相同的对象,从上面结果可见,通过new关键字创建的对象指向的是不同对象,使用字符串常量创建的指的是相同对象。
这是因为Java中的不可变字符串String常量采用字符串池(String Pool)管理技术,字符串池是一种字符串驻留技术。采用字符串常量赋值时,会在字符串池中查找字符串常量,如果已经存在,则把引用赋值给当前创建的字符串常量,否则创建字符串对象,并放到池中。
1.3字符串拼接
String字符串虽然是不可变字符串,但也可以进行拼接,只是会产生一个新的对象。String字符串拼接可以使用+运算符或String的concat(String str)方法。+运算符的优势是可以连接任何类型数据拼接成为字符串,而concat方法只能拼接String类型字符串。
public class stringConcat {
public static void main(String[] args) {
String s1="Hello";
//使用+运算符连接
String s2=s1+" ";
String s3=s2+"World";
System.out.println(s3);
String s4="Hello";
//使用+运算符连接,支持+=赋值运算符
s4+=" ";
s4+="World";
System.out.println(s4);
String s5="Hello";
//使用concat方法连接
s5=s5.concat(" ").concat("World");
System.out.println(s5);
java.util.Date now=new java.util.Date();
//对象拼接自动调用toString()方法
String s6="今天是:"+now;
System.out.println(s6);
}
}
运行结果:
Java中所有对象都有一个toString()方法,该方法可以将对象转换为字符串,拼接过程会调用该对象的toString()方法,将该对象转换为字符串后再进行拼接。
1.4字符串查找
在给定的字符串中查找字符或字符串是比较常见的操作。在String类中提供了indexOf和lastIndexOf方法用于查找字符或字符串,返回值是查找的字符或字符串所在的位置,-1表示没有找到。
字符串本质上是字符数组,因此它也有索引,索引从零开始。String的charAt(int index)方法可以返回索引index所在位置的字符。
public class stringSearch {
public static void main(String[] args) {
String sourceStr="There is a string accessing example.";
//获得字符串长度
int len=sourceStr.length();
//获得索引位置16的字符
char ch=sourceStr.charAt(16);
//查找字符和子字符串
int firstChar1=sourceStr.indexOf('r');
int lastChar1=sourceStr.lastIndexOf('r');
int firstStr1=sourceStr.indexOf("ing");
int lastStr1=sourceStr.lastIndexOf("ing");
int firstChar2=sourceStr.indexOf('e',15);
int lastChar2=sourceStr.lastIndexOf('e',15);
int firstStr2=sourceStr.indexOf("ing",5);
int lastStr2=sourceStr.lastIndexOf("ing",5);
System.out.println("原始字符串:"+sourceStr);
System.out.println("字符串长度:"+len);
System.out.println("索引16的字符:"+ch);
System.out.println("从前往后搜索r字符,第一次找到它所在的索引:"+firstChar1);
System.out.println("从后往前搜索r字符,第一次找到它所在的索引:"+lastChar1);
System.out.println("从前往后搜索ing字符串,第一次找到它所在的索引:"+firstStr1);
System.out.println("从后往前搜索ing字符串,第一次找到它所在的索引:"+lastStr1);
System.out.println("从索引为15位置开始,从前往后搜索e字符,第一次找到它所在索引:"+firstChar2);
System.out.println("从索引为15位置开始,从后往前搜索e字符,第一次找到它所在索引:"+lastChar2);
System.out.println("从索引为5位置开始,从前往后搜索ing字符串,第一次找到它所在索引:"+firstStr2);
System.out.println("从索引为5位置开始,从后往前搜索ing字符串,第一次找到它所在索引:"+lastStr2);
}
}
运行结果:
1.5字符串比较
字符串比较包括比较相等,比较大小,比较前后缀等。
比较前缀和后缀;
boolean endsWith(String suffix):测试此字符串是否以指定的后缀结束。
boolean startsWith(String suffix):测试此字符串是否以指定的前缀开始。
public class stringCompare {
public static void main(String[] args) {
String s1=new String("Hello");
String s2=new String("Hello");
//比较字符串是否是相同的引用
System.out.println("s1==s2:"+(s1==s2));
//比较字符串内容是否相等
System.out.println("s1.equals(s2):"+(s1.equals(s2)));
String s3="HELLO";
//忽略大小写比较字符串内容是否相等
System.out.println("s1.equalsIgnoreCase(s3):"+(s1.equalsIgnoreCase(s3)));
//比较大小
String s4="java";
String s5="Swift";
//比较字符串大小 s4>s5
System.out.println("s4.compareTo(s5):"+(s4.compareTo(s5)));
//忽略大小写比较字符串大小 s4<s5
System.out.println("s4.compareToIgnoreCase(s5):"+(s4.compareToIgnoreCase(s5)));
}
}
运行结果:
1.6字符串截取
public class stringCut {
public static void main(String[] args) {
String sourceStr="There is a string accessing example.";
//截取example.子字符串
String subStr1=sourceStr.substring(28);
//截取string子字符串
String subStr2=sourceStr.substring(11,17);
System.out.printf("subStr1=%s%n",subStr1);
System.out.printf("subStr2=%s%n", subStr2);
//使用split方法分隔字符串
System.out.println("-----使用split方法-----");
String[] array=sourceStr.split(" ");
for(String str:array)
{
System.out.println(str);
}
}
}
2.可变字符串StringBuffer和StringBuilder
Java提供了两个可变字符串类StringBuffer和StringBuilder。也叫“字符串缓冲区”。
StringBuffer是线程安全的,它的方法支持线程同步,线程同步会操作串行顺序执行,在单线程环境下会影响效率。StringBuilder是StringBuffer的单线程版本,它不是线程安全的,但它的执行效率很高。
(线程同步是一个多线程概念,就是当多线程访问一个方法时,只能由一个优先级别高的线程先访问,在访问期间会锁定该方法,其他线程只能等到它访问完成释放锁,才能访问。)
StringBuffer和StringBuilder具有完全相同的API,即构造方法和普通方法等内容一样。
2.1字符串长度和字符串缓冲区容量
字符串长度是指在字符串缓冲区中目前所包含的字符串长度,通过length()获得;
字符串缓冲区容量是缓冲区中所能容纳的最大字符数,通过capacity()获得。
字符串缓冲区容量默认值是16,达到最大容量的时候,它会将自身容量增加到当前的2倍再加2。而初始化长度=默认值+参数长度。看下面一个例子:
package builder;
public class LengthAndCapacity {
public static void main(String[] args) {
StringBuilder sbuilder1=new StringBuilder();
System.out.println("包含的字符串长度:"+sbuilder1.length());
System.out.println("字符串缓冲区容量:"+sbuilder1.capacity());
StringBuilder sbuilder2=new StringBuilder("hello");
System.out.println("包含的字符串长度:"+sbuilder2.length());
System.out.println("字符串缓冲区容量:"+sbuilder2.capacity());
//字符串缓冲区初始容量是16,超过之后会扩容。
StringBuilder sbuilder3=new StringBuilder();
for(int i=0;i<17;i++)
{
sbuilder3.append(8);
}
System.out.println("包含的字符串长度:"+sbuilder3.length());
System.out.println("字符串缓冲区容量:"+sbuilder3.capacity());
}
}
运行结果:
2.2字符串追加
package builder;
public class StringAppend {
public static void main(String[] args) {
StringBuilder sbuilder1=new StringBuilder("hello");
sbuilder1.append(" ").append("world");
sbuilder1.append(".");
System.out.println(sbuilder1);
StringBuilder sbuilder2=new StringBuilder();
Object obj=null;
//添加布尔值,转义符和空对象
sbuilder2.append(false).append('\t').append(obj);
System.out.println(sbuilder2);
StringBuilder sbuilder3=new StringBuilder();
for(int i=0;i<10;i++)
{
sbuilder3.append(i);
}
System.out.println(sbuilder3);
}
}
运行结果:
2.3字符串插入,删除和替换
package builder;
public class InsertDeleteReplace {
public static void main(String[] args) {
//原始不可变字符串
String str1="Java C";
//从不可变的字符串创建可变字符串对象
StringBuilder mstr=new StringBuilder(str1);
//插入字符串
mstr.insert(4," C++"); //在索引为4的字符位置之前插入" C++"
System.out.println(mstr);
//具有追加效果的插入字符串
mstr.insert(mstr.length()," Objective-C");
System.out.println(mstr);
//追加字符串
mstr.append(" and Swift");
System.out.println(mstr);
//删除字符串
mstr.delete(11,23); //删除指定索引范围内的字符(包含头不包含尾)
System.out.println(mstr);
}
}
运行结果: