String类有十多个重载的构造方法,可以使用byte数组、char数组或者另一个String对象来创建一个新的String对象。
查看Java中的String类的API文档,String类声明为final,意味着这个类不可继承,说明Java把String类作为一个标准的字符串操作类。
2、字符串的比较(==运算符与equal方法)
关系运算符==用于比较两个操作数是否相等,下面几个案例,将可以更好理解及如何比较两个String类型的变量是否相等。
package com.test;
public class StringTest {
public static void main(String[] args) {
String str1 = "abcde";
String str2 = "abcde";
if (str1 == str2) {
System.out.println("str1和str2相等");
} else {
System.out.println("str1和str2不相等");
}
}
}
上面代码运行的结果是:str1和str2相等
知识点:
- 在Java中,boolean、byte、short、int、long、char、float和double是基本数据类型,其它都是引用类型。也就是说,所有的对象类型都是引用类型。
- 所以,Java中的字符串都是String类型的对象,包括字符串字面常量,也就是说,“abc”是一个对象,是String类型的对象。
- 另外,==元算符是比较两个变量的值是否相等。
分析上面代码中的声明字符串变量str1和str2的定义语句:
String str1 = "abcde";
String str2 = "abcde";
第一行代码中的"abcde"是字符串字面常量,也是一个String类型的对象,Java编译器在常量池中分配内存空间并存储字符串序列,然后将该对象的引用赋值给字符串变量str1;
第二行中的"abcde"是字符串字面常量,Java编译器发现常量池中已经存在该对象,于是直接将该对象的引用值赋给变量str2,换句话说,编译器会把在程序中出现的相同内容的字符串字面常量视作同一个String对象。对于对象类型的变量,其值就是引用值,也可以理解为是对象的地址,比较运算符用于比较两个引用类型的变量时,比较的是它们的引用值是否相等。上面代码中的变量str1和str2指向的是同一个对象,那么运算符比较的结果是相等的。
看如下的代码,修改变量str1和str2的定义方法,运算的结果是:str1和str2不相等
public class StringTest {
public static void main(String[] args) {
String str1 = new String("abcde");
String str2 = new String("abcde");
if (str1 == str2) {
System.out.println("str1和str2相等");
} else {
System.out.println("str1和str2不相等");
}
}
}
分析上面代码,"abcde"是字符串字面常量,Java在常量池中分配内存并存储字符串序列,接下来new运算符要构造一个String类型的对象,于是用常量池中的字符串对象的内容在堆内存上构造一个新的String对象,并将新对象的引用值赋给变量。所以上面两行代码,两个new操作在堆内存上产生了两个不同的对象(有不同的内存空间),所以str1和str2指向的是不同的对象,故它们的引用值是不同的,用==运算符进行比较,比较的是引用值,结果自然是不相等的。
知识点:
- 当我们声明一个引用类型变量时,系统只为该变量分配了引用空间,并为创建一个具体的对象;当使用new操作符,将为对象分配空间,之后将对象的引用赋值给变量。
- 如果要比较两个对象的内容是否相等,需要使用对象的equals方法。在Java中,所有类都有一个共同的基类:java.lang.Object,在这个类中定义了一个方法equals,用于与另一个对象进行相等性判断,如果相等,返回true,否则返回false。
- Object类中的equals方法只有在两个引用值所指向同一个对象时才返回真true,所以不能直接使用Object类的equals方法,一般都是子类重写Object类的equals方法,提供自己的比较逻辑,String类作为Object的子类,也重写了equals方法,用于比较字符串对象内部所存储的字符串序列是否相等,也就是说String类的equals方法用来比较两个字符串对象的内容是否相等。
public class StringTest {
public static void main(String[] args) {
String str1 ="abcde";
String str2 = new String("abcde");
String str3 = new String("abcde");
if (str1.equals(str2)) {
System.out.println("str1和str2相等");
} else {
System.out.println("str1和str2不相等");
}
if (str2.equals(str3)) {
System.out.println("str2和str3相等");
} else {
System.out.println("str2和str3不相等");
}
}
}
上面代码运算的结果是:
str1和str2相等
str2和str3相等
3、compareTo方法
如果需要按照字典顺序(例如a小于b)来比较两个字符串的大小,可以使用String类的compareTo方法来比较两个字符串。如果当前字符串大于另一个字符串,compareTo方法返回一个正整数;如果相等,则返回0;如果小于则返回一个负整数。
public class StringCompareTo {
public static void main(String[] args) {
String str1 = "abc";
String str2 = "abf";
String str3 = new String("abc");
System.out.println(str1.compareTo(str2));
System.out.println(str2.compareTo(str1));
System.out.println(str1.compareTo(str3));
System.out.println(str3.compareTo(str1));
}
}
上面代码执行的结果如下:
-3
3
0
0
compareTo方法返回的是一个int值。这个方法会逐个比较两个字符串中各个字符的值,当遇到不同的字符时,它返回当前字符串减去另一个字符串在相同位置的字符值,也就是对相同位置的两个char类型的变量进行减法操作。
Java中,通常使用if语句中使用compareTo方法来判断两个字符串比较的结果,当结果小于0、大于0或者等于0时,分别执行对应操作。
4、字符串的拼接
在Java中,字符串的拼接是简单的,直接使用“+”运算符就可以了。还可以使用“+=”运算符。
String world = "World";
String res = "Hello " + world + "!";
String world = "World";
String res = "Hello";
res += world;
res += "!";
上面的操作,等同于调用String类的concat方法:
String world = "World";
String res = "Hello";
res = res.concat(world);
res = res.concat("!");
在Java中,“+”和“+=”运算符,除了可以应用于字符串对象,还可以应用其它的数据类型,例如:
String world = "World";
int i =3;
float f = 4.5f;
char ch = 'a';
boolean b = true;
System.out.println(world + i + f + ch + b);
输出结果:World34.5atrue
5、操作字符串的常用方法:
(1)获取字符串的长度:调用String类的length()方法,注意返回的是字符的数量,不是该字符串占用内存的大小。
String str = "Java 从入门到精通";
System.out.println(str.length());
(2)查找字符或字符串
查找字符串中是否存在某个字符或者某个子字符串,使用String类重载的4个indexOf方法,如下:
public int indexOf(int ch) // 参数ch是要查找的字符
public int indexOf(int ch,int fromIndex) // 参数fromIndex表示从哪个索引位置开始查找
public int indexOf(String str) // 参数str是要查找的子字符串
public int indexOf(String str,int fromIndex)
indexOf方法返回一个整数,默认从索引0位置开始查找,返回字符或者子字符串第一次出现的索引,如果没有找到,返回值是-1。
public class StringCompareTo {
public static void main(String[] args) {
String str = "Hello World";
System.out.println(str.indexOf('o')); // 输出4
System.out.println(str.indexOf('o',5)); // 输出7
System.out.println(str.indexOf("World")); // 输出6
System.out.println(str.indexOf("Welcome")); // 输出-1
}
}
String类也提供了反向查找字符或者子字符串的一组重载的lastIndexOf方法,如下所示:
public int lastIndexOf(int ch) // 参数ch是要查找的字符
public int lastIndexOf(int ch,int fromIndex) // 参数fromIndex表示从哪个索引位置开始查找
public int lastIndexOf(String str) // 参数str是要查找的子字符串
public int lastIndexOf(String str,int fromIndex)
将上面代码修改如下,结果将是:
public class StringCompareTo {
public static void main(String[] args) {
String str = "Hello World";
System.out.println(str.lastIndexOf('o')); // 输出7
System.out.println(str.lastIndexOf('o',5)); // 输出4
System.out.println(str.lastIndexOf("World")); // 输出6
System.out.println(str.lastIndexOf("Welcome")); // 输出-1
}
}
请注意lastIndexOf()方法,是从字符串的最后一个字符开始,查找字符或者子字符串在字符串第一次出现的字符,返回这个字符在字符串中的索引位置(从正面开始,索引值从0开始)。
(3)判断字符串的开始和结尾:startsWith() / endsWith()方法
// 测试字符串是否以指定的前缀开始
public boolean startsWith(String prefix)
// 测试字符串从指定的索引开始的子字符串是否以指定前缀开始
// 参数toffset表示在字符串中开始查找的位置
public boolean startsWith(String prefix,int toffset)
// 测试字符串是否以指定的后缀结尾
public boolean endsWith(String suffix)
String str = "代码test.jsp";
System.out.println(str.stratsWith("代码")); // true
System.out.println(str.endsWith(".jsp")); // false
(4)获取指定索引位置的字符:charAt(int index)
String str = "hello"; // 定义并初始化字符串变量str
int len = str.length(); // 获取字符串变量str的长度
char[] chaArr = new char[len]; // 定义一个字符型数组对象chArr,并初始化长度为str的字符个数
for (int i=0; i<len; i++) {
chArr[i] = str.charAt(i); // 给字符型数组变量chArr添加元素
}
System.out.println(charArr); // 输出:hello
另外,字符串转化为字符数组这个功能也经常会用到,Java中的String类提供了toCharArray()方法来实现。定义如下:
- public char[] toCharArray()
(5)截取子字符串
// 从指定索引位置截取子字符串,直到字符串的末尾
// public String substring(int beginIndex)
String str = "Hello World";
System.out.println(str.substring(6)); // 输出:World
// 从指定索引位置截取子字符串,直到索引endIndex-1处的字符,不包含endIndex索引字符
// public String substring(int beginIndex,int endIndex)
System.out.println(str.substring(6,10)); // 输出:Worl
substring方法可以和indexOf方法结合使用,先查找是否存在特定的字符或子字符串,在得到索引后开始截取。
String str = "Will Smith";
int index = str.indexOf("Smith"); // indexOf方法查找到子字符串“Smith”存在,返回字符“S”的位置
if (index != -1) {
System.out.println(str.substring(index,index+"Smith".length())); // 输出Smith
}
(6)分割字符串
public String[] split(String regex)
参数regex是用于进行匹配的正则表达式字符串,split方法根据参数regex返回一个保存了拆分后的各个字符串的数组。
String str = "zhansan,lisi,wangwu,zhaoliu";
String[] names = str.split(",");
for (String name : names) {
System.out.println(name);
}
输出如下:
zhansan
lisi
wangwu
zhaoliu
(7)替换字符或字符串
应用中替换字符串的部分内容是特别常见的。例如在某个字符串中含有敏感信息,或者不合规的字符串序列,在向用户显示时可以替换为*号。String类有两个重载的replace方法,一个用于替换字符,一个用于替换字符串。
- public String replace(char oldChar,char newChar)
用newChar替换字符串中所有的oldChar,并返回替换后的字符串。如果oldChar在这个String对象表示的字符串序列中没有出现,则直接返回该对象的引用,否则返回一个替换后的新的String对象。
- public String replace(CharSequence target , CharSequence replacement)
用replacement指定的字符序列替换字符串中出现的target字符序列。
String类中还有两个使用正则表达式来匹配要替换的字符串的方法:
- public String replaceFirst(String regex,String replacement)
用replacement替换此字符串匹配给定的正则表达式(regax)的第一个子串。
- public String replcceAll(String regex,String replacement)
用replacement替换此字符串匹配给定的正则表达式(regax)的所有子串。
String str = "habcjkmkabc";
Syttem.out.println(str.replaceFirst("abc","def"); // 输出:hdefjkmkabc
Syttem.out.println(str.replaceAll("abc","def"); // 输出:hdefjkmkdef
上面没有使用到正则表达式。
(8)合并字符串
在String类中有一个静态方法join,可以通过指定一个分隔符来合并字符串。
- public static String join(CharSequence delimiter, CharSequence… elements)
- delimited:分割字符串的分隔符
- elements:是变长参数,可以传入任意多个字符串
String names = String.join(",", "张山","李四","王二");
System.out.println(names); // 输出:张山,李四,王二
(9)重复字符串
String str = "abc";
System.out.println(str.repeat(5)); //输出abcabcabcabcabc
- public String repeat(int count)
将字符串重复参数count指定的次数,并串联起来返回一个新的字符串。
(10)大小写转换
- public String toLowerCase() :把字符串全部字符都转换为小写
- public String toUpperCase() :把字符串全部字符都转换为大写
Java没有提供首字母转为大写或小写方法,可以使用substring()和上面的方法结合实现相应的功能: