5.1 String类
5.1.1 声明字符串
字符串是常量,它们可以显示任何文字信息,字符串的值在创建之后不能更改。在Java语言中,单引号中的内容表示字符,例如's',而双引号中的内容则表示字符串,例如:
"我是字符串","123456789","上下,左右,东西,南北"
Java通过java.lang.String这个类来创建可以保存字符串的变量,所以字符串变量是一个对象。
声明一个字符串变量a,以及声明两个字符串变量a、b。代码如下:
String a
String a,b;
5.1.2 创建字符串
给字符串变量赋值有很多方法,下面分别介绍。
1.引用字符串的常量
String a ="时间就是金钱,我的朋友。";
String b= "锄禾日当午",C ="小鸡炖蘑菇";
string strl, str2;
strl ="We are students";
srt2 = "We are students";
2.利用构造方法实例化
String a = new String ("我爱清汤小肥羊");Stringb=new String(a) ;
3.利用字符数组实例化
char[] charArray ={'t','i','m','e',};String a=new String(charArray);
4.提取字符数组中的一部分创建字符串对象
char[] charArray ={'时','间','就','是','金','钱' };String a=new String(charArray,3,2);
例5.1
package 第五章;//包名
public class zy { //创建类
public static void main(String[] args) { //主方法
// TODO Auto-generated method stub
String a="时间就是金钱,我的朋友."; //直接引用字符串常量
System.out.println("a="+a); //输出a =时间就是金钱,我的朋友
String b= new String("我爱清汤小肥羊"); //利用构造方法实例化
String c= new String(b); //使用已有字符串变量实例化
System.out.println("b="+b); //输出字符串b的变量
System.out.println("c="+c); //输出字符串c的变量
char[] charArray= {'t','i','m','e'}; //利用字符数组实例化
String d= new String(charArray); //利用字符数组实例化
System.out.println("d="+d); //输出字符串d的变量
char[]charArray2= {'时','间','就','是','金','钱'}; //利用字符数组实例化
//提取字符数组部分内容,从下标为4的元素开始,截取2个字符
String e= new String(charArray2,4,2); //提取字符数组部分内容,从下标为4的元素开始,截取2个字符
System.out.println("e="+e); //输出字符串e的变量
}
}
例5.1运行结果
5.2 连接字符串
对于已声明的字符串,可以对其进行相应的操作。连接字符串就是字符操作中较简单的一种。可以对多个字符串进行连接,也可使字符串与其他数据类型进行连接。
5.2.1 连接字符串
使用“+”运算符可实现拼接多个字符串的功能,“+” 运算符可以连接多个字符串并产生一一个String对象。除了“+”运算符,“+=”同样可以实现字符串拼接。
例5.2
package 第五章;
public class zy { //创建类
public static void main(String[] args) { //主方法
// TODO Auto-generated method stub
String a="abc"; //定义abc
String b="123"; //定义123
String c=a+b+"!"; //使用"+"拼接字符串
String d="拼接字符串"; //拼接字符串
d+=c; //使用"+="拼接字符串
System.out.println("a="+a); //连接a相等
System.out.println("b="+b); //连接b相等
System.out.println("c="+c); //连接c相等
System.out.println("d="+d); //连接d相等
}
}
例5.2运行结果
5.2.2 连接其他数据类型
字符串也可同其他基本数据类型进行连接。如果将字符串同这些数据类型进行连接,会将这些数据直接转换成字符串
例5.3
package 第五章;
public class zy {//创建类
public static void main(String[] args) {//主方法
// TODO Auto-generated method stub
int booktime=4;//声明的int型变量booktime
float practice=2.5f;//声明的float型变量practice
System.out.println("我每天花费"+booktime+"小时看书;"+practice+"小时上机练习");//将字符串与整型、浮点型变量相连,并将结果输出
}
}
例5.3运行结果
5.3 提取字符串信息
字符串作为对象,可以通过相应的方法获取字符串的有效信息,如获取某字符串的长度、某个索引位置的字符等。本节将介绍几种获取字符串信息的方法。
5.3.1 获取字符串长度
length0方法返回采用UTF-16的编码表示字符的数量,也就是char的数量
str.length();
例如:定义一个字符串num,使用length()方法获取其长度。
string num ="12345 678910";
int size =num.length();
将size输出,得出的结果就是:
11
这个结果将字符串num的长度赋值给int型变量size,此时变量size的值为11,这表示length()方法返回的字符串长度包括字符串中的空格。
5.3.2 获取指定的字符
charAt(string index)方法将可指定索引出的字符返回。
str. charAt (index);
str: 任意字符串对象。
index: char值的索引。
例5.4
package 第五章;
public class zy {//创建类
public static void main(String[] args) {//主方法
// TODO Auto-generated method stub
String str="床前明月光,疑是地上霜。";//创建字符串对象str
char chr=str.charAt(4);//将字符串str中索引位置为4的字符赋值给chr
System.out.println("字符串中索引位置为4的字符是:"+chr);//输出chr
}
}
例5.4运行结果
5.3.3 获取子字符索引位置
1.indexOf(String str)
语法如下:
a.indexof(substr);
a:任意字符串对象
substr:要搜索的字符串
查找字符e在字符串str中首次出现的索引位置;
string str ="We are the world";
int size =str.indexof('e'); //size的值为1
例5.5
package 第五章;
public class zy {//创建类
public static void main(String[] args) {//主方法
String str = "12345abcde"; / 创建字符串对象
int charIndex = str.indexOf("abc");// 获取字符串str中"abc"首次出现的索引,赋值给charIndex
if (charIndex != -1) {// 判断:index的值不等于-1
System.out.println("str中存在abc字符串");// 如果index不等于-1,则执行此行代码,说明str中存在“abc”字符串
} else {//else语句
System.out.println("str中没有abc字符串");//输出没有abc的字符串
}
}
}
例5.5运行结果
2.indexOf(String srt,int fromindex)
语法如下;
a.indexof(str,fromindex);
a:任意字符串对象
str:要搜索的子字符串
fromindex:开始搜索的索引位置
例5.6
package 第五章;
public class zy { //创建类
public static void main(String[] args) { //主方法
// TODO Auto-generated method stub
String str = "We are the world"; // 创建字符串
int firstIndex = str.indexOf("r"); // 获取字符串中"r"第一次出现的索引位置
int secondIndex = str.indexOf("r", firstIndex + 1); // 获取字符串中"r"第二次出现的索引位置,从第一次出现的索引位置之后开始查找
int thirdIndex = str.indexOf("r", secondIndex + 1); // 获取字符串中"r"第三次出现的索引位置,从第二次出现的索引位置之后开始查找
System.out.println("e第一次出現的索引位置是:" + firstIndex); //输出e出现的第一次索引位置
System.out.println("e第二次出現的索引位置是:" + secondIndex); //输出e出现的第二次索引位置
System.out.println("e第三次出現的索引位置是:" + thirdIndex); //输出e出现的第三次索引位置
}
}
例5.6运行结果
3.pubile int lastindexOf(String srt)
语法如下;
a.lastindexof(str);
a:任意字符串对象
str:要搜索的字符串
例5.7
package 第五章;
public class zy { //创建类
public static void main(String[] args) { //主方法
// TODO Auto-generated method stub
String str = "Let it go!Let it go!"; // 创建字符串对象
int gIndex = str.lastIndexOf("g"); // 返回”g“最后一次出现的位置
int goIndex = str.lastIndexOf("go"); // 返回”go“最后一次出现的位置
int oIndex = str.lastIndexOf("o"); // 返回”o“最后一次出现的位置
System.out.println("字符串\"Let it go!Let it go\"中:\n"); //输出字符串
System.out.println("\"g\"最后一次出现的位置是:" + gIndex); //输出”g“最后一次出现的位置
System.out.println("\"o\"最后一次出现的位置是:" + oIndex); //输出”o“最后一次出现的位置
System.out.println("\"go\"最后一次出现的位置是:" + goIndex); //输出”go“最后一次出现的位置
}
}
例5.7运行结果
4.lastindexOf(String srt,int fromindex)
语法如下;
a.lastindexof(str,fromindex);
a:任意字符串
srt:要搜索的子字符串
fromindex:开始搜索的索引位置
例5.8
package 第五章;
public class zy { //创建类
public static void main(String[] args) { //主方法
// TODO Auto-generated method stub
String str = "01a3a56a89"; // 返回字母"a"最后一次出现的索引位置
int lastIndex = str.lastIndexOf("a"); //返回字母"a"的索引位置otherIndex
// 满足0<=fiveBeforeIndex<=5条件,在满足条件的结果集中,返回最大的数字
int fiveBeforeIndex = str.lastIndexOf("a", 5); // 返回字母"a"的索引位置otherIndex
int threeBeforeIndex = str.lastIndexOf("a", 3); // 满足0<=threeBeforeIndex<=3条件,在满足条件的结果集中,返回最大的数字
System.out.println("字符串\"01a3a56a89\"中:\n"); //输出字符串
System.out.println("字母\"a\"最后一次出现的位置是:" + lastIndex); //输出a最后一次出现的位置
System.out.println("从索引位置5开始往回搜索,字母\"a\"最后一次出现的位置:" + fiveBeforeIndex); //输出索引位置5开始往回搜索“a”最后一次出现的位置
System.out.println("从索引位置3开始往回搜索,字母\"a\"最后一次出现的位置:" + threeBeforeIndex); //输出索引位置3开始往回搜索“a”最后一次出现的位置
}
}
例5.8运行结果
5.3.4 判断字符串首尾内容
1.starsWith(String prefix)
语法如下;
str.startsWith(prefix);
srt:任意字符串
prefix:作为前缀的字符串
例5.9
package 第五章;
public class zy { //创建类
public static void main(String[] args) { //主方法
// TODO Auto-generated method stub
String myDream1 = "我有一个梦想,幽谷上升,高山下降;"; // 前半句
String myDream2 = "坎坷曲折之路成坦途,圣光披露,满照人间。"; // 后半句
System.out.println(myDream1 + myDream2 + "\n\t\t————马丁·路德金《我有一个梦想》\n"); // 判断前半句是否以"我有一个梦想"为前缀
boolean firstBool = myDream1.startsWith("我有一个梦想"); // 判断后半句是否以"我有一个梦想"为前缀
boolean secondBool = myDream2.startsWith("我有一个梦想"); // 判断前半句的逻辑结果
if (firstBool) { //判断if语句
System.out.println("前半句是以\"我有一个梦想\"开始的。"); // 判断后半句的逻辑结果
} else if (secondBool) { //使用连接语句
System.out.println("后半句是以\"我有一个梦想\"开始的。"); // 如果没有符合条件的字符串
} else { //else语句
System.out.println("没有以\"我有一个梦想\"开始的。"); //输出最后逻辑结果
}
}
}
例5.9运行结果
2.starsWith(String prefix,int toffset)
语法如下;
str.startsWith(prefix,index);
srt:任意字符串
prefix:作为前缀的字符串
index:开始查询位置
例5.10
package 第五章;
public class zy { //创建类
public static void main(String[] args) { //主方法
// TODO Auto-generated method stub
String str = "床前明月光,疑是地上霜。\n举头望明月,低头思故乡。"; // 打印古诗
System.out.println("《静夜思》\n" + str + "\n"); // 返回换行符所在的位置
int enterIndex = str.indexOf("\n"); // 返回从换行符之后开始的子字符串前缀是否为”举“。
boolean flag = str.startsWith("举", enterIndex + 1); // 换行符在字符串中只占一个字符,所以enterIndex + 1
if (flag) { //if语句
System.out.println("第二行是以\"举\"开始的"); // 如果结果为真,则输出此句
} else { // else语句
System.out.println("第二行是以\"" + str.charAt(enterIndex + 1) + "\"开始的"); // 如果结果为假,则输出第二行开头第一个字符
}
}
}
例5.10运行结果
3.endsWith(String suffix)
语法如下;
str.endWith(suffix);
srt:任意字符串
suffix:指定的后缀字符串
例5.11
package 第五章;
public class zy { //创建类
public static void main(String[] args) { //主方法
// TODO Auto-generated method stub
String str1 = "你说完了吗?"; //以"?"结尾
String str2 = "我说完了。"; //以"。"结尾
boolean flag1 = str1.endsWith("。"); // 判断str1是否以"。"结尾
boolean flag2 = str2.endsWith("。"); // 判断str2是否以"。"结尾
System.out.println("字符串str1是以句号结尾的吗?" + flag1); // 输出结果
System.out.println("字符串str2是以句号结尾的吗?" + flag2); //输出结果
}
}
例5.11运行结果
5.3.5 获取字符数组
tocharArray()方法可以将字符串转换为一个字符数组。
str.tocharArray();
其中,str表示任意字符串
例5.12
package 第五章;
public class zy { //创建类
public static void main(String[] args) { //主方法
// TODO Auto-generated method stub
String str = "这是一个字符串"; //创建一个字符串
char[] ch = str.toCharArray(); //将字符串转换成字符数组
for (int i = 0; i < ch.length; i++) { //遍历字符数组
System.out.println("数组第" + i + "个元素为:" + ch[i]); //输出数组的元素
}
}
}
例5.12运行结果
5.3.6 判断子字符串是否存在
contains()方法可以判断字符串中是否包含指定的内容。
str.contains (String);
str:任意字符串
String:查询子字符串
例5.13
package 第五章;
public class zy { //创建类
public static void main(String[] args) { //主方法
// TODO Auto-generated method stub
String str = "今天的菜单有:蒸羊羔,蒸熊掌,蒸鹿尾。烧花鸭,烧雏鸡,烧子鹅,卤煮咸鸭,酱鸡,腊肉,松花小肚。"; //创建字符串
System.out.println(str); // 输出字符串
boolean request1 = str.contains("腊肉"); // 判断字符串中是否有“腊肉”的字样
System.out.println("今天有腊肉吗?" + request1); //输出结果
boolean request2 = str.contains("汉堡"); // 判断字符串中是否有“汉堡”的字样
System.out.println("今天有汉堡吗?" + request2); //输出结果
}
}
例5.13运行结果
5.4 字符串操作
5.4.1 截取字符串
1.substring(int beginIndex)
该方法返回一个新的字符串,它是此字符中的一个子字符申。 该子字符申从指定索引处的字符开始,直到此字符串末尾
语法如下;
str. substring (beginIndex);
str:任意字符串。
beginIndex:起始索引(包括)。
例5.14
package 第五章;
public class zy { //创建类
public static void main(String[] args) { //主方法
// TODO Auto-generated method stub
String str = "为革命保护视力,眼保健操开始!"; //输入字符串
String substr = str.substring(8); //从第8位开始截取字符串
System.out.println("字符串str的后半句是:" + substr); //输出字符串
}
}
例5.14运行结果
2.substring(int beginIndex,int endIndex)
该方法返回一个新字符串,它是此字符串的一个子字付串。该于字符串从指定的beginIndex处开始,直到索引endIndex- 1处的字符。
语法如下;
Str. substring (beginIndex, endIndex);
str:任意字符串。
beginIndex:起始索引(包括)。
endIndex:结束索引(不包括)。
例5.15
package 第五章;
public class zy { //创建类
public static void main(String[] args) { //主方法
// TODO Auto-generated method stub
String str = "闭门造车,出门合辙。"; // 从0开始(即从头开始)截取至4-1索引位置的子字符串
String substr = str.substring(0, 4); //输入0到4的字符串
System.out.println("字符串str的前半句是:" + substr); //输出前半句的字符串
}
}
例5.15运行结果
5.4.2 字符串替换
1. replace(CharSequence target, CharSequence replacement)
该方法可以实现将指定的字符序列替换成新的字符序列。CharSequence 是一个接口, 代表一个可读的字符序列,String、 StringBuffer 、StringBuilder 都实现了这个接口,所以可以直接将字符当成参数。
语法如下;
str.replace(oldstr,newstr);
str: 任意字符串。
oldstr:要被替换的字符序列。
newstr:替换后的字符序列。
例5.16
package 第五章;
public class zy { //创建类
public static void main(String[] args) { //主方法
// TODO Auto-generated method stub
String str="明月几时有,把酒问青天"; //输入信息
String restr=str.replace("月", "日"); //将str中的”月“全部替换成”日“
System.out.println("字符串str替换之后的效果:"+restr); //输出信息
}
}
例5.16运行结果
2. replaceAll(String regex, String replacement)
该方法可以实现将指定的字符串替换成新的字符串,支持正则表达式。
语法如下;
str. replaceAll (regex, replacement) ;
str: 任意字符串。
regex: 被替换的字符串或正则表达式。
replacement:替换后的字符串。
例5.17
package 第五章;
class zy { //创建类
public static void main(String[] args) { //主方法
// TODO Auto-generated method stub
String str = "0123456789abc\\d"; // 使用replace()将符合"\\d"表达式的字符串替换"?"
String restr = str.replace("\\d", "?"); // 使用replaceAll()将符合"\\d"表达式的字符串替换"?"
String restrAll = str.replaceAll("\\d", "?"); // 输出结果
System.out.println("字符串str:" + str); //输出字符串str
System.out.println("使用replace()替换的结果:" + restr); //替换字符串replace结果
System.out.println("使用replaceAll()替换的结果:" + restrAll); //替换字符串replaceAll结果
}
}
例5.17运行结果
3. replaceFirst(String regex, String replacement)
语法如下;
str.replaceFirst (regex, replacement) ;
str:任意字符串。
regex: 第一个被替换的字符串或正则表达式。
replacement: 替换后的字符串。
例5.18
package 第五章;
public class zy { //创建类
public static void main(String[] args) { //主方法
// TODO Auto-generated method stub
String str = "8I want to marry you, so I need you!"; // 创建字符串
String noNumber = str.replaceFirst("\\d", ""); // 将开头的数字替换成两个双引号""
String youToHer = noNumber.replaceFirst("you", "her"); // 将第一次出现的"you"替换成"her"
System.out.println("替换之后的结果是:"+youToHer); // 输出结果
}
}
例5.18运行结果
5.4.3 字符串分割
1.split(String regex)
该方法可根据给定的分隔符对字符串进行拆分,支持正则表达式,最后返回一个字符串数组。
语法如下;
str.split(regex);
str:任意字符串。
regex:分隔符表达式
例5.19
package 第五章;
public class zy { //创建类
public static void main(String[] args) { //主方法
// TODO Auto-generated method stub
String str = "从前有座山,山里有个庙,庙里有个小松鼠"; // 创建一个字符串
String[] strArray = str.split(","); // 让字符串按照","进行分割
for (int i = 0; i < strArray.length; i++) { // 使用for循环,循环输出数字所有元素
System.out.println("数组第" + i + "索引的元素是:" + strArray[i]); //输出索引的元素
}
}
}
例5.19运行结果
如果想定义多个分隔符,可以使用符号"|"。如果用"|"分隔字符串,需要使用转义字符"\\|"。
例5.20
package 第五章;
public class zy { //创建类
public static void main(String[] args) { //主方法
// TODO Auto-generated method stub
String str = "a1b2,c,d e f|gh"; // 创建字符串,包含多种类型字符
String[] a1 = str.split(","); // 使用","分割
String[] a2 = str.split(" "); // 使用空格分割
String[] a3 = str.split("\\|"); // 使用"|"分割
String[] a4 = str.split("\\d"); // 使用正则表达式分割,本行用数字分割
String[] a5 = str.split(",| |\\||\\d"); // 同时用","、空格、"|"、数字分割,用符号"|"连接所有分隔符
System.out.println("str的原值:[" + str + "]"); //显示str的原值
System.out.print("使用\",\"分割:"); // 使用for-each循环展示","分割的结果
for (String b : a1) { //for语句
System.out.print("[" + b + "]"); //输出+b+
}
System.out.println(); //换行
System.out.print("使用空格分割:"); // 使用for-each循环展示空格分割的结果
for (String b : a2) { // for语句
System.out.print("[" + b + "]"); //输出+b+
}
System.out.println(); // 换行
System.out.print("使用\"|\"分割:"); // 使用for-each循环 展示"|"分割的结果
for (String b : a3) { //for语句
System.out.print("[" + b + "]"); //输出+b+
}
System.out.println(); //换行
System.out.print("使用數字分割:"); // 使用for-each循环展示数字分割的结果
for (String b : a4) { //for语句
System.out.print("[" + b + "]"); //输出+b+
}
System.out.println(); //换行
System.out.print("同時使用所有分隔符:"); // 使用for-each循环展示所有分隔符同时分割的结果
for (String b : a5) { //for语句
System.out.print("[" + b + "]"); //输出+b+
}
System.out.println(); //输出信息
}
}
例5.20运行结果
2. sit(tigi regex, int limit)
该方法可根据给定的分隔符对字符串进行拆分,并限定拆分的次数,支持正则表达式。
语法如下;
str,split(regex, limit)
str:任意字符串。
regex: 分隔符表达式。
limit: 限定的分割次数。
例5.21
package 第五章;
public class zy { //创建类
public static void main(String[] args) { //主方法
String str = "192.168.0.1"; // 创建字符串
String[] firstArray = str.split("\\."); // 按照"."进行分割
String[] secondArray = str.split("\\.", 2); // 按照"."进行两次分割
System.out.println("str的原值为:[" + str + "]"); // 输出str原值
System.out.print("全部分割的结果:"); // 输出全部分割的结果
for (String a : firstArray) { //字符串用for循环
System.out.print("[" + a + "]"); // 输出a原值
}
System.out.println(); // 换行
System.out.print("分割两次的结果:"); //输出分割两次结果的信息
for (String a : secondArray) { //字符串用for循环
System.out.print("[" + a + "]");// 输出a原值
}
System.out.println(); //换行
}
}
例5.21运行结果
5.4.4 大小写转换
1. toLowerCase()
该方法将String转换为小写。如果字符串中没有应被转换的字符,则将原字符串返回;否则将返回一个新的字符串,将原字符串中每个可进行小写转换的字符都转换成等价的小写字符。字符长度与原字符长度相同。
语法如下;
str. toLowerCase () ;
str: 任意字符串。
2. toUpperCase()
该方法将String转换为大写。如果字符串中没有应被转换的字符,则将原字符串返回:否则返回一个新字符串,将原字符串中每个可进行大写转换的字符都转换成等价的大写字符。新字符长度与原字符长度相同。
str. toUpperCase() ;
其中,str 表示任意字符串。
例5.22
package 第五章;
public class zy { //创建类
public static void main(String[] args) { //主方法
// TODO Auto-generated method stub
String str = "abc DEF"; // 创建字符串
System.out.println(str.toLowerCase()); // 按照小写格式输出
System.out.println(str.toUpperCase()); // 按照大写格式输出
}
}
例5.22运行结果
5.4.5 去除空白内容
trim()方法可以返回字符串的副本,忽略首尾空白处,语法如下;
str.trim();
其中,str表示任意字符串。
例5.23
package 第五章;
public class zy { //创建类
public static void main(String[] args) { //主方法
String str = " abc "; // 输入信息
String shortStr = str.trim(); //输入trim的字符串
System.out.println("str的原值是:[" + str + "]"); //str的原值的字符串
System.out.println("去掉首尾空白的值:[" + shortStr + "]"); //去掉首尾空白的值
}
}
例5.23运行结果
例5.24
package 第五章;
public class zy { //创建类
public static void main(String[] args) { //主方法
String str = " a b cd e f g "; // 创建字符串
String shortstr = str.replaceAll("\\s", ""); // 利用正则表达式,将字符串中所有的空白内容都替换成””
System.out.println("str的原值是:[" + str + "]"); // 输出结果
System.out.println("删除空内容之后的值是:[" + shortstr + "]"); //输出删除空内容之后的值
}
}
例5.24运行结果
5.4.6 比较字符串是否相等
对字符串对象进行比较不能简单地使用比较运算符“==”,因为比较运算符比较的是两个字符串的内存地址是否相同。因为即使两个字符串的文本值相同,两个对象的内存地址也可能不同,以使用比较运算符会返回false。
例5.25
package 第五章;
public class zy { //创建类
public static void main(String[] args) { //主方法
// TODO Auto-generated method stub
String tom, jerry; // 直接引入字符串常量
tom = "I am a student"; //定义Tom字符串
jerry = "I am a student"; //定义jerry字符串
System.out.println("直接引入字符串常量的比较结果:" + (tom == jerry)); // 使用new创建信对象
tom = new String("I am a student"); //定义新的Tom字符串
jerry = new String("I am a student"); //定义新的Jerry字符串
System.out.println("使用new创建对象的比较结果:" + (tom == jerry)); //输出新的创建对象的比较结果
}
}
例5.25运行结果
为什么第一个结果是true,第二个结果是false呢?因为这两种赋值方法在计算机中处理的方式不同,像字符串 常量这样的字面值, 会直接放在栈中。例子5.25中tom 和jrry直接用字符串常量不同。其字符串值保存的是一个指向栈中 数据的引用。又因为两个对象引用的是同一个常量,用“==””出较发现两者指向了相同的地址,所以结果会返回true
如果 tom和jrry创建了新对象, 计算机处理方式就不一一样了。当tom使用new方法时,会在中创建一个新的Sring对象,并为这个对象单独在栈中创建值,即使与栈中已有相同数据,也不会共享。用“二”比较发现两者指向不同的对象地址,结果会返回flse
想要比较两个字符串对象的内容是否相同,就需要用equals()和equalsIgnoreCase()方法。
1. equals(String str);
将此字符串与指定的对象比较。当且仅当该参数不为null, 并且是与此对象表示相同字符序列的Sring对象时,结果才为true。
语法如下:
a.equals(str);
a:任意字符串。
st:进行比较的字符串。
例5.26
package 第五章;
public class zy { //创建类
public static void main(String[] args) { //主方法
// TODO Auto-generated method stub
String str1 = "Hello"; //定义为"Hello"
String str2 = new String("Hello"); //定义新的"Hello"
String str3 = new String("你好"); //定义新的"你好"
String str4 = str2; //赋值
System.out.println("str1 == str2 的结果:" + (str1 == str2)); //str1结果等于str2
System.out.println("str1 == str3 的结果:" + (str1 == str3)); //str1结果等于str3
System.out.println("str1 == str4 的结果:" + (str1 == str4)); //str1结果等于str4
System.out.println("str2 == str4 的结果:" + (str2 == str4)); //str2结果等于str4
System.out.println("str1.equals(str2) 的结果:" + str1.equals(str2)); //输出结果
System.out.println("str1.equals(str3) 的结果:" + str1.equals(str3)); //输出信息
System.out.println("str1.equals(str4) 的结果:" + str1.equals(str4)); //输出信息
}
}
例5.26运行结果
2. equalslgnoreCase(String anotherString);
将此字符串对象与指定的对象比较,不考虑大小写。如果两个字符串的长度相同,并且其中棚应的字符都相等(忽略大小写),则认为这两个字符串是相等的。
语法如下:
a.equalsIgnoreCase (anotherString) ;
a:任意字符串。
anthrstring: 进行比较的字符串。
例5.27
package 第五章;
public class zy { //创建类
public static void main(String[] args) { //主方法
String str1 = "abc"; // 创建字符串对象,内容全部小写
String str2 = "ABC"; // 创建字符串对象,内容全部大写
System.out.println("区分大小写的结果:"+str1.equals(str2)); // 比较两个字符串的内容是否相等
System.out.println("不区分大小写的结果:"+str1.equalsIgnoreCase(str2)); // 比较两个字符串的内容是否相等,不区分大小写
}
}
例5.27运行结果
5.4.7 格式化字符串
String类的静态format()方法用于创建格式化的字符串。format(方法有两种重载形式。
(1) format(tring format,Object.. args)
该方法使用指定的格式字符串和参数返回一个格式化字符串,格式化后的新字符串使用本地默认的语言环境。
语法如下:
str. format (String format, Object...args)
format: 格式字符串。
args:格式字符串中由格式说明符引用的参数。如果还有格式说明符以外的参数,则忽略这些额外的参数。此参数的数目是可变的,可以为0。
(2 ) format(Local 1,String format,Object... args)
1:格式化过程中要应用的语言环境。如果1为null,则不进行本地化。
format:格式字符串。
yargs: 格式字符串中由格式说明符引用的参数。如果还有格式说明符以外的参数,则忽略这
些额外的参数。此参数的数目是可变的,可以为0。
1.日期和时间字符串格式化
在应用程序设计中,经常需要显示时间和日期。如果想输出满意的日期和时间格式,股需要 0-包首现丽编写大量的代码经过各种算法才能实现。format()方 法通过给定的特殊转换符作为参数来实现对日期
和时间的格式化。
(1)日期格式化
先来看下面的例子,返回一个月中的天数。实例代码如下:
Date date = new Date(); //创建Date对象date
string s = String. format ("&te", date);//通过format ()方法对date进行格式化
例5.28
package 第五章;
import java.util.Date; //导入java.util.Date类
public class zy { //创建类
public static void main(String[] args) { //主方法
// TODO Auto-generated method stub
Date date = new Date(); //创建Date对象date
String year = String.format("%tY", date); //将date进行格式化
String month = String.format("%tB", date); //将date月份进行格式化
String day = String.format("%td", date); //将date天进行格式化
System.out.println("今年是:" + year + "年"); //输出年的结果
System.out.println("现在是:" + month); //输出月的结果
System.out.println("今天是:" + day + "号"); //输出天的结果
}
}
例5.28运行结果
(2)时间格式化
使用format()方法不仅可以完成起的格式化,也可以实现时间的格式化,时间格式化转化为仿佛要比日期转换时更多、更精确,它可以将时间格式化为时、分、秒、毫秒。
例5.29
package 第五章;
import java.util.Date; //导入java.util.Date类
public class zy { //创建类
public static void main(String[] args) { // 主方法
Date date = new Date(); // 创建Date对象date
String hour = String.format("%tH", date); // 将date进行格式化
String minute = String.format("%tM", date); // 将date进行格式化
String second = String.format("%tS", date); // 将date进行格式化
System.out.println("现在是:" + hour + "时" + minute + "分" + second + "秒"); //输出现在的时、分、秒
}
}
例5.29运行结果
(3) 格式化常见的日期时间组合
格式化日期与时间的转换符定义了各种日期时间组合的格式。
例5.30
package 第五章;
import java.util.Date; //导入java.util.Date类
public class zy { //创建类
public static void main(String[] args) { //主方法
// TODO Auto-generated method stub
Date date = new Date(); // 创建Date对象date
String time = String.format("%tc", date); // 将date格式化
String form = String.format("%tF", date); //将date格式化
System.out.println("全部的时间信息是:" + time); // 将格式化后的日期时间输出
System.out.println("年-月-日格式:" + form); //输出年—月—日格式信息
}
}
例5.30运行结果
例5.31
package 第五章;
public class zy { //创建类
public static void main(String[] args) { //主方法
String str1 = String.format("%c", 'X'); // 输出字符
System.out.println("字母x大写:" + str1); // 输出结果
String str2 = String.format("%d", 1251 + 3950); // 输出百分号和数字
System.out.println("1251+3950的结果是:" + str2); // 输出小数点后两位
String str3 = String.format("%.2f", Math.PI); // 输出百分号和数字
System.out.println("π取两位小数点:" + str3); // 输出布尔值
String str4 = String.format("%b", 2 < 3); // 输出结果
System.out.println("2<3的结果是:" + str4); // 输出哈希散列码,等同Integer.toHexString(3015); //输出结果
String str5 = String.format("%h", 3510); // 输出%h
System.out.println("3510的hashCode值:" + str5); //输出信息
String str6 = String.format("%o", 33); //输出%o
System.out.println("33的8进制结果是:" + str6); // 输出8进制
String str7 = String.format("%x", 33); //输出%x
System.out.println("33的16进制结果是:" + str7); // 输出16进制
String str8 = String.format("%e", 120000.1); //%e
System.out.println("120000.1用科学计数法表示:" + str8); // 输出科学计数法
String str9 = String.format("%a", 40.0); //输出%a
System.out.println("40.0的十六进制浮点值:" + str9); // 输出带有效位数和指数的16进制浮点值
System.out.println(String.format("天才是由%d%%的灵感,%d%%的汗水 。", 1, 99)); // 输出百分号和数字
}
}
例5.31运行结果
例5.32
package 第五章;
public class zy { //创建类
public static void main(String[] args) { //主方法
String str1 = String.format("%5d", 123); // 让字符串输出的最大长度为5,不足长度在前端补空格
System.out.println("输出长度为5的字符串|" + str1 + "|"); // 让字符串左对齐
String str2 = String.format("%-5d", 123); // 让字符串输出的最小长度为5,不足长度在前端补空格
System.out.println("左对齐|" + str2 + "|"); // 在8进制前加一个0
String str3 = String.format("%#o", 33); //输出%#o
System.out.println("33的8进制结果是:" + str3); // 在16进前加一个0x
String str4 = String.format("%#x", 33); //输出%#x
System.out.println("33的16进制结果是:" + str4); // 显示数字正负号
String str5 = String.format("%+d", 1); //输出%+d
System.out.println("我是正数:" + str5); // 显示数字正负号
String str6 = String.format("%+d", -1); //输出%+d
System.out.println("我是负数:" + str6); // 在正数前补一个空格
String str7 = String.format("% d", 1); //输出%d
System.out.println("我是正数,前面有空格" + str7); // 在负数前补一个负号
String str8 = String.format("% d", -1); //输出%d
System.out.println("我是负数,前面有负号" + str8); // 让字符串输出的最大长度为5,不足长度在前端补0
String str9 = String.format("%05d", 12); //输出%05d
System.out.println("前面不够的数用0填充:" + str9); // 用逗号分隔数字
String str10 = String.format("%,d", 123456789); //输出%,d
System.out.println("用逗号分隔:" + str10); // 正数无影响
String str11 = String.format("%(d", 13); //输出%d
System.out.println("我是正数,我没有括号:" + str11); // 让负数用括号括起来
String str12 = String.format("%(d", -13); //输出d
System.out.println("我是负数,我有括号的:" + str12); //输出信息
}
}
例5.32运行结果
5.5 可变字符串
StringBuffer是线程安全的可变字符序列,一个类似于 String的字符串缓冲区。前面内容介绍过String创建的字符串对象是不可修改的,这一节介绍的SuigBufter类创造的字字符串序列是可修改的且实体容量会随着存放的字符串增加而自动增加。StringBulder 与StringBuffer有完全相同的API.只是为了提高效率而放弃了线程安全控制。
5.5.1 StringBuffer 类的常用方法
1.创建StringBuffer类
创建一一个新的StringBuffer对象必须用new方法,而不能像String对象那样直接引用字符串常量。
语法如下:
StringBuffer sbf = new StringBuffer() ;//创建一个对象,无初始值
StringBuffer sbf = new StringBuffer ("abc") ;//创建一个对象,初始值为“abc"
StringBuffer sbf = new StringBuffer(32); //创建一个对象, 初始容量为32个字符
2. append()方法
将参数转换成字符串,将所得字符串中的字符追加到此序列中。
语法如下:
sbf:append (obj);
sbf:任意StingBuffer 对象。
例5.33
package 第五章;
public class zy { //创建类
public static void main(String[] args) { //主方法
StringBuffer sbf = new StringBuffer("门前大桥下,"); // 创建StringBuffer对象
sbf.append("游过一群鸭,"); // 追加字符串常量
StringBuffer tmp = new StringBuffer("快来快来数一数,"); // 追加StringBuffer对象
sbf.append(tmp); // 追加整型变量
int x = 24678; //定义x
sbf.append(x); // 输出信息
System.out.println(sbf.toString()); //换行
}
}
例5.33运行结果
3. setCharAt(int index, char ch)方法
将给定索引处的字符修改为ch。
语法如下:
sbf . setCharAt (index, ch) ;
sbf:任意StringBuffer对象。
index:被替换字符的索引。
ch:替换后的字符。
例5.34
package 第五章;
public class zy { //创建类
public static void main(String[] args) { //主方法
// TODO Auto-generated method stub
StringBuffer sbf = new StringBuffer("0123456"); //创建新的字符串
System.out.println("sbf的原值是:" + sbf); //输出sbf的原值
sbf.setCharAt(3, 'A'); // 将索引为3的字符改成'A'
System.out.println("修改后的值是:" + sbf); //输出sbf修复后的值
}
}
例5.34运行结果
4. iner(int offet, String str)方法
语法如下;
sbf. insert (offset,str) ;
sbf: 任意 StringBuffer 对象
offset:插入的索引。
str:插入的字符串。
例5.35
package 第五章;
public class zy { //创建类
public static void main(String[] args) { //主方法
// TODO Auto-generated method stub
StringBuffer sbf = new StringBuffer("0123456"); //创建新的字符串
System.out.println("sbf的原值为:"+sbf); //输出sbf的原值
sbf = sbf.insert(5, "F"); //在索引为5的位置插入"F",将返回值赋给sbf自己
System.out.println("修改之后的值为:"+sbf); //输出sbf修复后的值
}
}
例5.35运行结果
5. reverse()方法
该方法可以将字符串反序输出。
语法如下:
sbf. reverse() ;
其中,sbf表示任意StringBuffer对象。
例5.36
package 第五章;
public class zy { //创建类
public static void main(String[] args) { //主方法
StringBuffer sbf = new StringBuffer("同一个世界,同一个梦想"); //定义新的值
System.out.println("sbf的原值为:" + sbf); //输出sbf的原值
sbf = sbf.reverse(); // 将字符序列sbf反转
System.out.println("修改之后的值为:" + sbf); //输出修复后的值
}
}
例5.36运行结果
6. delete(int start, int end)方法
移除此序列的子字符串中的字符。该子字符串是从
指定的索引start处开始,一直到索引 end一1处,如果
end-1超出最大索引范围,则一直到序列尾部。如果start等于end,则不发生任何更改。
语法如下:
sbf.delete (start, end)
sbf:任意StringBuffer 对象。
start: 起始索引(包含)。
end: 结束索引(不包含)。
例5.37
package 第五章;
public class zy { //创建类
public static void main(String[] args) { //主方法
// TODO Auto-generated method stub
StringBuffer sbf = new StringBuffer("天行健,君子以自强不息"); //定义新的字符串
System.out.println("sbf的原值为:"+sbf); //输出sbf的原值
sbf = sbf.delete(4, 7); //删除从索引4开始至索引7之前的内容
System.out.println("删除之后的值为:"+sbf); //输出删除后的值
}
}
例5.37运行结果
7.其他方法
除了这几个常用方法以外,StringBuffer 还有类似String类的方法。
例5.38
package 第五章;
public class zy { //创建类
public static void main(String[] args) { //主方法
// TODO Auto-generated method stub
StringBuffer sbf = new StringBuffer("ABCDEFG"); // 创建字符串序列
int lenght = sbf.length(); // 获取字符串序列的长度
char chr = sbf.charAt(5); // 获取索引为5的字符
int index = sbf.indexOf("DEF"); // 获取DEF字符串所在的索引位置
String substr = sbf.substring(0, 2); // 截取从索引0开始至索引2之间的字符串
StringBuffer tmp = sbf.replace(2, 5, "1234"); // 将从索引2开始至索引5之间的字符序列替换成"1234"
System.out.println("sbf的原值为:" + sbf); //输出sbf的原值
System.out.println("sbf的长度为:" + lenght); //输出sbf的长度
System.out.println("索引为5的字符为:" + chr); //输出索引为5的字符
System.out.println("DEF字符串的索引位置为:" + index); //输出索引位置
System.out.println("索引0开始至索引2之间的字符串:" + substr); //输出索引0到2之间的字符串
System.out.println("替换后的字符串为:" + tmp); //输出替换后的字符串
}
}
例5.38运行结果
5.5.2 StringBuilder类的使用方法
StringBuilder类与StringBuffer类具有兼容的API,所以两者的使用方法也相同。
例5.39
package 第五章;
public class zy { //创建类
public static void main(String[] args) { //主方法
StringBuilder sbd = new StringBuilder(); //定义新的值
System.out.println("sbd的原值为空"); //输出sbd的原值
sbd.append("我是StringBuilder类"); //输出信息
System.out.println("sbd追加字符串:" + sbd); //输出字符串sbd
int length = sbd.length(); //定义length
System.out.println("sbd的长度为:" + length); //输出信息
sbd = sbd.insert(length - 1, "123456"); //新增数据
System.out.println("插入字符串:" + sbd); //输出信息
sbd = sbd.delete(sbd.length() - 1, sbd.length()); //在原数据的基础上减一
System.out.println("删除最后一个字:" + sbd); //删除最后一个字
sbd = sbd.reverse(); //反序
System.out.println("反序输出:" + sbd); //输出反序的值
}
}
例5.39运行结果
5.5.3 StringBuffer、 StringBuilder、 String 之间的关系
1. StringBuffer、 StringBuilder、 String 互相转换
StringBuffer类和StringBuilder 类都有toStringO方法,可以返回字符序列的字符串表示形式。这两个类在初始化的时候,可以通过字符串作为参数,指定初始化的字符序列内容。
例5.40
package 第五章;
public class zy { //创建类
public static void main(String[] args) { //主方法
String str = "String"; // String转换成StringBuffer
StringBuffer sbf = new StringBuffer(str); // String转换成StringBuilder
StringBuilder sbd = new StringBuilder(str); // StringBuffer转换成String
str = sbf.toString(); // StringBuilder转换成String
str = sbd.toString(); // StringBuffer转换成StringBuilder
StringBuilder bufferToBuilder = new StringBuilder(sbf.toString()); // StringBuilder转换成StringBuffer
StringBuffer builderToBuffer = new StringBuffer(sbd.toString()); // StringBuilder转换成StringBuffer
}
}
2. StringBuffer、 StringBuilder、 String 的不同之处
String只能赋值一次, 每二次内容发生改变都生成了一个新的对象,然后原有的对象引用新的象,所以说String本身是不可改变。每一次改变String的字符串内容,都会在内存创建新的对象,每一次生成新对象都会对系统性能产生影响
而StringBuffer和StringBuilder不同,每次操作都是对自身对象做操作,而不是生成新的对象
SrigBufer和SrngBider也存在不同之处。StringBuffer 的方法都使用"synchronized"关键字进行修饰,这样保证了同时最多只有一个线程可以运行这些方法,也就是保证了线程安全。StringBuilder则不具备这样的特点。反过来说,正因为StringBuilder 没有线程安全机制,运行起来就不用考虑给线程加锁,所以运行效率会比StringBuffer 要高。
例5.41
package 第五章;
public class zy { //创建类
public static void main(String[] args) { // 主方法
String str = ""; // 创建空字符串
long starTime = System.currentTimeMillis(); // 定义对字符串执行操作的起始时间
for (int i = 0; i < 10000; i++) { // 利用for循环执行10000次操作
str = str + i; // 循环追加字符串
}
long endTime = System.currentTimeMillis(); // 定义对字符串操作后的时间
long time = endTime - starTime; // 计算对字符串执行操作的时间
System.out.println("String循环1万次消耗时间:" + time); // 将执行的时间输出
StringBuilder builder = new StringBuilder(""); // 创建字符串生成器
starTime = System.currentTimeMillis(); // 定义操作执行前的时间
for (int j = 0; j < 10000; j++) { // 利用for循环进行操作
builder.append(j); // 循环追加字符
}
endTime = System.currentTimeMillis(); // 定义操作后的时间
time = endTime - starTime; // 追加操作执行的时间
System.out.println("StringBuilder循环1万次消耗时间:" + time); // 将操作时间输出
StringBuilder builder2 = new StringBuilder(""); // 创建字符串生成器
starTime = System.currentTimeMillis(); // 定义操作执行前的时间
for (int j = 0; j < 50000; j++) { // 利用for循环进行操作
builder2.append(j); // 循环追加字符
}
endTime = System.currentTimeMillis(); // 定义操作后的时间
time = endTime - starTime; // 追加操作执行的时间
System.out.println("StringBuilder循环5万次消耗时间:" + time); // 将操作时间输出
}
}
例5.41运行结果
(1)操作少,数据少,用string。
(2)单线程,操作多,数据多,用stringBuilder。
(3)多线程,操作多,数据多,用stringBuffer
5.6 小结
因为在日常开发工作中,处理字符串的代码在程序中占据很大比例,所以对理解、学习和操作字符序列打下基础,可谓是学习编程的重中之重。本章学习了很多字符串操作:如何获取字符串的内容和长度;如何查找某个位置的字符内容;还有如何将字符串改成读者想要的内容。针对不同的需求,还要懂得如何将已有的字符串用最简洁的方式变成我们需要的结果。
另外,从栈堆的角度,描述了字符串是如何在内存中操作的,这使读者可以更好地了解不同类在不同场景下的优势与劣势,今后不管是开发小程序,还是大型项目,都能够找到合适的解决方案,让编写的程序更加健壮、稳定。