目录
5.5.3 StringBuffer、StringBuilder、String之间的关系
5.1 String类
5.1.1 声明字符串
字符串是常量,它们可以显示任何文字信息,字符串的值在创建之后不能更改。单引号中的内容表示字符,例如's',而双引号中的内容则表示字符串,例如:
"我是字符串",“123456789”,"上下 左右 东西 南北"
Java通过java.lang.String这个类来创建可以保存字符串的变量,所以字符串变量是一个对象。声明一个字符串变量a,以及声明两个字符串变量a、b。代码如下:
String a;
String a,b;
注意:
在不给字符串变量赋值的情况下,默认值为null,就是空对象,如果此时调用Sring的方法会发生空指针异常。
5.1.2 创建字符串
1. 引用字符串变量
例如,直接将字符串变量赋值给String类型变量,代码如下:
String a="时间就是金钱,我的朋友。";
String b="锄禾日当午",c="小鸡炖蘑菇";
String str1,str2;
str1="We are students";
str2="We are students";
2. 利用构造方法实例化
例如,使用new关键字创建对象。代码如下:
String a=new String("我爱清汤小肥羊");
String b=new String(a);
3. 利用字符数组实例化
例如,定义一个字符数组charArray,使用该字符数组创建一个字符串。代码如下:
char[] charArray={'t','i','m','e'};
String a=new String(charArray);
4. 提取字符数组中的一部分创建字符串对象
例如,定义一个字符数组charArray,从该字符数组索引3 的位置开始,提取两个元素,创建一个字符串,代码如下:
char[] charArray={'时','间','就','是','金','钱'};
String a=new String(charArray,2,3);
例5.1 编写一段代码,声明多个字符串变量,用不同的赋值方法给这些字符串变量赋值并输出。
代码如图所示:
运行结果如图所示:
5.2 连接字符串
对于已声明的字符串,可以对其进行相应的操作。连接字符串就是字符操作中较简单的一种。可以对多个字符串进行连接,也可使字符串与其他数据类型进行连接。
5.2.1 连接字符串
使用“+”运算符可实现拼接多个字符串的功能,“+”运算符可以连接多个字符串并产生一个String对象。除了“+”运算符,“+=”同样可以实现字符串拼接。
例5.2 使用“+”和“+=”拼接字符串。
代码如图所示:
运行结果如图所示:
5.2.2 连接其他数据类型
字符串也可同其他基本数据类型进行连接。如果将字符串同这些数据类型进行连接,会将这些数据直接转换成字符串。
例5.3 在项目中创建类Link,在主方法中创建数值型变量,实现将字符串与整型、浮点型变量相连的结果输出。
代码如图所示:
运行结果如图所示:
注意:
只要“+”运算符的一个操作数是字符串,编译器就会将另一个操作数转换成字符串形式,所以应谨慎地将其他数据类型与字符串相连,以免出现意想不到的结果。
如果将上例中的输出语句修改为:
System.out.println(”我每天花费”+booktime+”小时看书;"+(practice+booktime)+”小时上机练习”);
由于运算符是有优先级的,圆括号的优先级最高,所以先被执行,再将结果与字符串相连。
注意:
字符串在计算公式中的先后顺序会影响运算结果。
String a="1”+2+3+4 一“1234" //碰到字符串后,直接输出后面内容
String b= 1+2+3+"4" 一"64” //碰到字符串前,先做运算,后输出内容
String c="1"+(2+3+4)一"19” //碰到字符串后,先运算括号中的值,后输出内容
5.3 提取字符串信息
字符串作为对象,可以通过相应的方法获取字符串的有效信息,如获取某字符串的长度、某个索引位置的字符等。
5.3.1 获取字符串长度
length)方法返回采用UTF-16的编码表示字符的数量,也就是char的数量,语法如下:
str.length();
例如,定义一个字符串num,使用length)方法获取其长度。代码如下:
String num ="12345 67890”;
int size = num.length();
将size输出,得出的结果就是:
11
5.3.2 获取指定的字符
charAt(String index)方法可将指定索引处的字符返回。语法如下:
str.charAt(index);
str: 任意字符串对象
index: char值的索引
例5.4 创建字符串对象,查看字符串中索引位置是4的字符。
代码如图所示:
运行结果如图所示:
5.3.3 获取子字符串索引位置
Sting类提供了两种查找字符串的方法,即indexOf与lastndexOf)方法。indexOf)方法返回的是搜索的字符或字符串首次出现的位置,lastIndexOf0方法返回的是搜索的字符或字符串最后一次出现的位置。
1. indexOf(String str)
该方法用于返回参数字符串在指定字符串str中首次出现的索引位置。当调用字符串的indexOf方法时,会从当前字符串的开始位置搜索str的位置;如果没有检索到字符串str,该方法的返回是-1。
语法如下:
a.indexOf(substr);
a: 任意字符串对象
substr: 要搜索的字符串
查找字符e在字符串str中首次出现的索引位置。代码如下:
Stringstr="We are theworld";
int size=str.indexOf('e'); //size的值为1
例5.5 创建字符串对象str,判断str中是否包含子字符串"abc"。
代码如图所示:
运行结果如图所示:
2. indexOf(String str, int fromlndex)
从指定的索引fromIndex开始至字符串最后,返回指定子字符串在此字符串中第一次出现处的索引。如果没有检索到字符串str,该方法的返回值同样是-1。
语法如下:
a.indexof(str,fromIndex);
a:任意字符串对象
str:要搜索的子字符串
fromIndex: 开始搜索的索引位置
例5.6查找字符串“We are the world”中“r”第一、二、三次出现的索引位置。
代码如图所示:
运行结果如图所示:
3. public int lastlndexOf(String str)
返回指定子字符串在此字符串中最右边出现处的索引。语法如下:
lastIndexOf(str);
a:任意字符串
str: 要搜索的字符串
例5.7 查找字符出“Tet it go!Let it go!”中单词“go”最后出现的位置。
代码如图所示:
运行结果如图所示:
4. lastlndexOf(String str,int fromlndex)
返回指定子字符串在此字符串中最后一次出现处的索引,从指定的索引开始反向搜索。
语法如下:
a. lastIndexOf(str, fromIndex);
a:任意字符串
str:要搜索的子字符串
fromlndex:开始搜索的索引位置
例5.8 查询字符出“01a3a56a89”中字母“a”的位置。
代码如图所示:
运行结果如图所示:
5.3.4 判断字符串首尾内容
startsWithO方法和 endsWith)方法分别用于判断字符串是否以指定的内容开始或结束。这两个方法的返回值都是boolean类型。
1. startsWith(String prefix)
该方法用于判断字符串是否以指定的前缀开始。语法如下:
str.startsWith(prefix);
str:任意字符串
prefix: 作为前缀的字符串
例 5.9 查看一个字符串是否以“我有一个梦想”开始。
代码如图所示:
运行结果如图所示:
2. startsWith(String prefix,int toffset)
该方法用于判断从指定索引开始的子字符串是否以指定的前缀开始。语法如下:
str.startsWith(prefix, index);
str:任意字符串
prefix:作为前缀的字符串
index:开始查找的位置
例5.10查询五言绝句《静夜思》的第二行是否以“举”字开头。
代码如图所示:
运行结果如图所示:
3. endsWith(String suffix)
该方法判断字符串是否以指定的后缀结束。语法如下:
str.endsWith(suffix);
str:任意字符串
suffix:指定的后缀字符串
例5.11 查看一个字符串是否以句号结尾。
代码如图所示:
运行结果如图所示:
5.3.5 获取字符数组
toCharArray()方法可以将字符串转换为一个字符数组。语法如下:
str.toCharArray();
其中,str表示任意字符串
例5.12 创建一个字符串,将此字符串转换成一个字符数组,并分别输出字符数组中的每个元素。
代码如图所示:
运行结果如图所示::
5.3.6 判断子字符串是否存在
contains()方法可以判断字符串中是否包含指定的内容。语法如下:
str. contains (string);
str:任意字符串
string:查询的子字符串
例5.13 创建字符串,输出相声中的《报菜名》,然后用contains方法查看是否有“腊肉”和“汉堡”这两道菜。
代码如图所示:
运行结果如图所示:
5.4 字符串的操作
5.4.1 截取字符串
1. substring(int beginlndex)
该方法返回一个新的字符串,它是此字符串的一个子字符串。该子字符串从指定索引处的字符开始,直到此字符串末尾。
语法如下:
str.substring(beginIndex);
str:任意字符串
beginIndex:起始索引(包括)
例 5.14输出字符串“为革命保护视力,眼保健操开始!”的最后半句话。
代码如图所示:
运行结果如图所示:
2. substring(int beginlndex, int endlndex)
该方法返回一个新字符串,它是此字符串的一个子字符串。该子字符串从指定的beginIndex处开始,直到索引endIndex-1处的字符。
语法如下:
str.substring(beginIndex, endIndex);
str: 任意字符串
beginlndex:起始索引(包括)
endIndex:结束索引(不包括)
例5.15 取字符串“闭门造车,出门合辙。”的前半句话。
代码如图所示:
运行结果如图所示:
5.4.2 字符串替换
1. replace(CharSequence target, CharSequence replacement)
该方法可以实现将指定的字符序列替换成新的字符序列。CharSequence是一个接口,代表一个可读的字符序列,String、StringBuffer、StringBuilder都实现了这个接口,所以可以直接将字符串当成参数。
语法如下:
str.replace(oldstr, newstr);
str:任意字符串
oldstr:要被替换的字符序列
newstr:替换后的字符序列
例5.16字符串“明月几时有,把酒问青天”中的“月”替换成“日”。
代码如图所示:
运行结果如图所示:
2. replaceAll(String regex, String replacement)
该方法可以实现将指定的字符串替换成新的字符串,支持正则表达式。语法如下:
str.replaceAll(regex, replacement);
str:任意字符串
regex: 被替换的字符串或正则表达式
replacement: 替换后的字符串
例 5.17 分别使用replace()方法和replaceAl10方法,利用正则表达式将字符串中所有的数字替换成“?”。
代码如图所示:
运行结果如图所示:
3. replaceFirst(String regex, String replacement)
该方法可以实现将第一个指定的字符串替换成新的字符串,支持正则表达式。
str.replaceFirst(regex, replacement);
str:任意字符串
regex: 第一个被替换的字符串或正则表达式
replacement:替换后的字符串
例 5.18 现有字符串"8I want to marry you,so I need you!",去掉第一个数字,再把第一次出现的"you"替换成"her"。
代码如图所示:
运行结果如图所示:
5.4.3 字符串分割
1.split(String regex)
该方法可根据给定的分隔符对字符串进行拆分,支持正则表达式,最后返回一个字符串数组。语法如下:
str.split(regex);
str: 任意字符串
regex:分隔符表达式
例5.19 创建一个字符串,用”,”分割。
代码如图所示:
运行结果如图所示:
如果想定义多个分隔符,可以使用符号”!”。如果用”I“分割字符串,需要使用转义字符”\”。
例 5.20 同时使用不同的分隔符,分割同一字符串。
代码如图所示:
运行结果如图所示:
2. split(String regex, int limit)
该方法可根据给定的分隔符对字符串进行拆分,并限定拆分的次数,支持正则表达式。语法如下:
str.split(regex,limit)
str:任意字符串
regex:分隔符表达式
limit:限定的分割次数
例 5.21 将字符串“192.168.0.1”按照“.”拆分两次,第一次全部拆分,第二次拆分两次。
代码如图所示:
运行结果如图所示:
5.4.4 大小写转换
1. toLowerCase()
该方法将String转换为小写。如果字符串中没有应被转换的字符,则将原字符串返回;否则将返回一个新的字符串,将原字符串中每个可进行小写转换的字符都转换成等价的小写字符。字符长度与原字符长度相同。
语法如下:
str.toLowerCase();
str:任意字符串
2. toUpperCase()
该方法将String转换为大写。如果字符串中没有应被转换的字符,则将原字符串返回;否则返回一个新字符串,将原字符串中每个可进行大写转换的字符都转换成等价的大写字符。新字符长度与原字符长度相同。
语法如下:
str.toUpperCase();
其中,str表示任意字符串。
例 5.22 将字符串“abc DEF”分别用大写、小写两种格式输出。
代码如图所示:
运行结果如图所示:
5.4.5 去除空白内容
trim()方法可以返回字符串的副本,忽略首尾处空白。语法如下:
str.trim();
其中,str表示任意字符串。
例5.23 使用trim)方法去掉字符串两边的空白内容。
代码如图所示:
运行结果如图所示:
例5.24 利用正则表达式"\\s",将字符串中所有的空白内容替换成空字符。
代码如图所示:
运行结果如图所示:
5.4.6 比较字符串是否相等
对字符串对象进行比较不能简单地使用比较运算符“==”,因为比较运算符比较的是两个字符串的内存地址是否相同。因为即使两个字符串的文本值相同,两个对象的内存地址也可能不同,所以使用比较运算符会返回false。
例5.25 使用比较运算符比较两个字符串。
代码如图所示:
运行结果如图所示:
1.equals(String str);
将此字符串与指定的对象比较。当且仅当该参数不为null,并且是与此对象表示相同字符序列的String 对象时,结果才为true。语法如下:
a.equals(str);
a:任意字符串
str: 进行比较的字符串
例 5.26 创建String变量,分别用“=”和equals)方法判断两个字符串是否相等。
代码如图所示:
运行结果如图所示:
2. equalslgnoreCase(String anotherString);
将此字符串对象与指定的对象比较,不考虑大小写。如果两个字符串的长度相同,并且其中相应的字符都相等(忽略大小写),则认为这两个字符串是相等的。语法如下:
a.equalsIgnoreCase(anotherString);
a:任意字符串
anotherString:进行比较的字符串
例 5.27 使用 equals)和equalsIgnoreCase方法判断两个字符串是否相等。
代码如图所示:
运行结果如图所示:
5.4.7 格式化字符串
String类的静态format)方法用于创建格式化的字符串。format(方法有两种重载形式。
(1) format(String format,Object...args)
该方法使用指定的格式字符串和参数返回一个格式化字符串,格式化后的新字符串使用本地默认的语言环境。语法如下:
str.format(String format,Object…args)
format: 格式字符串。
args: 格式字符串中由格式说明符引用的参数。如果还有格式说明符以外的参数,则忽略这些额外的参数。此参数的数目是可变的,可以为0。
(2) format(Local l,String format,Object...args)
1:格式化过程中要应用的语言环境。如果1为null,则不进行本地化。
format: 格式字符串。
args: 格式字符串中由格式说明符引用的参数。如果还有格式说明符以外的参数,则忽略这些额外的参数。此参数的数目是可变的,可以为0。
1.日期和时间字符串格式化
(1)日期格式化
下面的例子,返回一个月中的天数。实例代码如下:
Date date = new Date(); //创建Date对象date
String s =String.format("te", date); //通过format()方法对date进行格式化
上述代码中变量s的值是当前日期中的天数,如今天是15号,则s的值为15;%te是转换符,常用的日期格式化转换符如表5.1所示:
例 5.28 在项目中创建类Eval,实现将当前日期信息以4位年份、月份全称、2位日期形式输
出。
代码如图所示:
运行结果如图所示:
(2)时间格式化
使用 format方法不仅可以完成日期的格式化,也可以实现时间的格式化。时间格式化转换符要比日期转换符更多、更精确,它可以将时间格式化为时、分、秒、毫秒。格式化时间的转换符如表5.2所示:
例 5.29 在项目中创建类GetDate,实现将当前时间信息以2位小时数、2位分钟数、2位秒数
形式输出。
代码如图所示:
运行结果如图所示:
(3)格式化常见的日期时间组合
格式化日期与时间的转换符定义了各种日期时间组合的格式,其中最常用的日期和时间的组合格式如表5.3所示:
例5.30 在项目中创建类DateAndTime,在主方法中实现将当前日期时间的全部信息以指定格格式的日期输出。
代码如图所示:
运行结果如图所示:
2. 常规类型格式化
常规类型的格式转化可应用于任何参数类型,可以通过表5.4所示的转换符来实现。
例5.31 实现不同类型的格式转化。
代码如图所示:
运行结果如图所示:
使用转换符,还可以配合转换符标识来控制输出的格式,如表5.5所示。
例 5.32 使用标识控制字符串的输出格式。
代码如图所示:
运行结果如图所示:
5.5 可变字符串
5.5.1 StringBuffer类的常用方法
1.创建StringBuffer类 扫一
创建一个新的StringBuffer对象必须用new方法,而不能像String对象那样直接引用字符串常量。语法如下:
StringBuffer sbf = new StringBuffer(); //创建一个对象,无初始值
StringBuffer sbf = newStringBuffer("abc"); //创建一个对象,初始值为“abc”
StringBuffer sbf = new StringBuffer(32); //创建一个对象,初始容量为32个字符
2. append()方法
将参数转换成字符串,将所得字符串中的字符追加到此序列中。语法如下:
sbf.append(obj);
sbf:任意StringBuffer对象。
obj:任意数据类型的对象,例如String、int、double、Boolean等,都转变成字符串的表示形式。
例 5.33 创建StringBuffer对象,使用append()追加字符序列。
代码如图所示:
运行结果如图所示:
3. setCharAt(int index, char ch)方法
将给定索引处的字符修改为ch。语法如下:
sbf.setCharAt(index, ch);
sbf:任意StringBuffer对象
index:被替换字符的索引
ch: 替换后的字符
例 5.34 创建一个 StringBuffer对象,将索引为3的字符修改成'A'。
代码如图所示:
运行结果如图所示:
4. insert(int offset, String str)方法
将字符串插入此字符序列中。语法如下:
sbf.insert(offset,str);
sbf:任意StringBuffer对象
offset: 插入的索引
str: 插入的字符串
例 5.35 创建一个StringBuffer对象,在索引为5的位置插入字符串“F”。
代码如图所示:
运行结果如图所示:
5. reverse()方法
该方法可以将字符串反序输出。语法如下:
sbf.reverse();
其中,sbf表示任意StringBuffer对象。
例5.36 创建一个 StringBuffer对象,将其字符序列反序输出。
代码如图所示:
运行结果如图所示:
6. delete(int start,int end)方法
移除此序列的子字符串中的字符。该子字符串是从指定的索引start处开始,一直到索引end-1处,如果end-1超出最大索引范围,则一直到序列尾部。如果 start等于end,则不发生任何更改。
语法如下:
sbf.delete (start, end)
sbf:任意StringBuffer对象
start: 起始索引(包含)
end:结束索引(不包含)
例 5.37 创建一个StringBuffer对象,删除从索引4开始至索引7之前的内容。
代码如图所示:
运行结果如图所示:
7.其他方法
除了这几个常用方法以外,StringBuffer还有类似String类的方法。
例 5.38 StringBuffer类中类似String类的方法。
代码如图所示:
运行结果如图所示:
5.5.2 StringBuilder类的使用方法
StringBuilder类与StringBuffer类具有兼容的API,所以两者的使用方法也相同。
例 5.39 创建StringBuilder字符序列对象,对其做追加、插入、删除和反序输出操作。
代码如图所示:
运行结果如图所示:
5.5.3 StringBuffer、StringBuilder、String之间的关系
1. StringBuffer、StringBuilder、String互相转换
StringBuffer类和 StringBuilder类都有toString0方法,可以返回字符序列的字符串表示形式。这两个类在初始化的时候,可以通过字符串作为参数,指定初始化的字符序列内容。
例 5.40 创建StringBuffer对象、StringBuilder对象、String对象,并将三者的内容互相转换。
代码如图所示:
2. StringBuffer、StringBuilder、String的不同之处
String 只能赋值一次,每一次内容发生改变都生成了一个新的对象,然后原有的对象引用新的对象,所以说String本身是不可改变。每一次改变String的字符串内容,都会在内存创建新的对象,而每一次生成新对象都会对系统性能产生影响。而StringBuffer和StringBuilder不同,每次操作都是对自身对象做操作,而不是生成新的对象,其所占空间会随着字符内容增加而扩充,做大量的修改操作时,不会因生成大量匿名对象而影响系统性能。
StringBuffer 和StringBuilder也存在不同之处。StringBuffer的方法都使用”synchronized"关键字进行修饰,这样保证了同时最多只有一个线程可以运行这些方法,也就是保证了线程安全。StringBulder则不具备这样的特点。反过来说,正因为StringBuilder没有线程安全机制,运行起来就不用考虑给线程加锁,所以运行效率会比StringBuffer要高。
例5.41 在项目中创建类Jerque,在主方法中编写如下代码,验证字符串操作和字符串生成器操作的效率。
代码如图所示:
运行结果如图所示:
StringBuffer、StringBuilder、String的区别
根据表中内容,还可以总结这些类的适用场景:
(1)操作少、数据少,用String
(2)单线程,操作多,数据多,用StringBuilder
(3)多线程,操作多,数据多,用StringBuffer