来自微信公众号:开点工作室(ID:kaidiancs)
Java中提供了String类型,这是一个类,使用它可以方便地处理字符串。Java中的字符串是一个真正的对象,而不像其他语言那样是一个零结尾的字符数组。
1 String类型简述
String类型的对象是内存中连续排列的一个或多个字符,分为常量和变量两种。所有的字符串常量,如"yikes!",都实现为本类的实例。字符串常量由0个或多个字符组成,包括转义序列。字符串常量由双引号括起来。所以,下面例子中的每一个都是合法的字符串常量:
""
"2468"
"I must\n go home"
系统为程序中出现的字符串常量自动创建一个String对象,如语句:
System.out.println("This is aString");
将创建"This is a String"对象,这个创建过程是隐含的。
Java提供的标准包java.lang中封装了类String,这是不变字符串类。不变字符串是指字符串一旦创建,其长度和内容就不能改变。比如,对String类的实例进行查找、比较、连接等操作时,既不能输入新字符,也不能改变字符串的长度。对于那些需要改变内容并有许多操作的字符串,Java提供了StringBuffer类来处理。
String类中封装了许多方法,用来对字符串进行操作。
2 字符串说明及初始化
Java程序中的字符串分常量和变量两种。对于字符串变量,在使用之前要显式说明,并进行初始化。字符串的说明很简单,如下所示。
String s1;
同样可以创建一个空的字符串:
String s1 = new String();
也可以由字符数组创建字符串,如下所示。
char chars[] = {'a', 'b', 'c'};
String s2 = new String( chars );
当然,可以直接用字符串常量来初始化一个字符串,这和基本数据类型是一样的:
String s = "abc";
这等价于
String s = new String("abc");
上面两种说明都表示s指向一个String对象,其内容是"abc"。
还可以为String引用重新赋值,如下所示。
String s = "John";
s = "Harry";
这等价于
String s = new String("John");
s = new String("Harry");
String对象是不可改变的,这意味着,在它们构造后没有方法来改变它们。上面的这两条语句似乎是改变了引用s的值,但实际上,"John"没有被改变,它只是被丢弃了!引用s现在指向一个新的String对象:"Harry"。如下这样对s的重新赋值也是可行的:
s = s + " Windsor";
现在s指向对象"Harry Windsor"。
初始化String对象的其他方法如下所示。
String s1 = null; //s1 is a null reference
String s2 = new String(); //s2 is an empty character equence
String state = "Alaska";
String dessert = "baked " + state; // dessert hasvalue "baked Alaska"
程序1 字符串操作。
public class StringTest
{ publicstatic void main(String args[])
{ String s = "This is a testString!";
System.out.println("beforechanged, s= " + s);
Stringt = s.toLowerCase();
System.out.println("afterchanged, s= " + s);
System.out.println("t=" + t);
}
}
程序1的执行结果如下所示。
before changed, s= This is a test String!
after changed, s= This is a test String!
t= this is a test string!
进行toLowerCase()操作前后,s的内容并没有改变,而该操作的结果是在内存中又生成一个新的对象"this is a test string!",该实例赋给了变量t。
3. 几个特殊处理
连接
给定两个String类型的运算数lhs和rhs,lhs+rhs的结果是一个字符串,由lhs后跟rhs组成,即字符串的前半部分是lhs,后半部分是rhs,这称为字符串的连接或拼接。如果lhs或rhs是一个对象而不是一个字符串,在连接lhs和rhs之前先调用对象的toString方法。连接操作可以连续操作,从而将多个字符串拼接起来。
int five = 5;
String state = "Hawaii-";
String tvShow = state + five +"-0"; //tvShow has value"Hawaii-5-0"
假定Date类有toString方法,它输出日期,格式为:2/17/1948。
Date d1 = new Date(8, 2, 1947);
Date d2 = new Date(2, 17, 1948);
String s = "My birthday is " + d2; // s hasvalue"My birthday is 2/17/1948"
String s3 = d1.toString() + d2.toString(); // s3 has value8/2/19472/17/1948
如果连接操作数之一是一个字符串,另一个是基本数据类型,则非字符串操作数先转化为字符串,然后再做连接。如果lhs或rhs都不是串对象,则抛出错误。
int x = 3, y = 4;
String sum = x + y; // error:can't assign int 7 to String
String s2 = d1 + d2; // error: +not defined for objects
如果连接操作数之一是对象,另一个是字符串,则对象的toString方法可以省略。实现连续拼接时要注意操作数的次序。如下所示。
System.out.println(d1+" "+d2);
System.out.println(d1+d2+" "); // 错误,因为先计算d1+d2,都不是字符串
System.out.println(d1+" ");
System.out.println(" "+d1);
String s = d1+""+d2;
System.out.println("s= "+s);
String类对象可以使用concat(String str)方法将str连接在当前字符串的尾部。例如:
String s = "This is the ";
String t = s.concat("String.");
t的内容为:"This is theString."。
2. 比较
有两个方法可用来比较String对象,如下所示。
(1)使用从Object类继承来的equals方法,并按照实际需要进行重写。例如,
if (string1.equals(string2))...
如果string1和string2是相同的字符串,返回真,否则返回假。
(2)使用compareTo方法。String类实现了Comparable接口,这意味着在String类中提供了compareTo方法。该方法按字典序比较两个串,规则如下。
如果 string1.compareTo(string2)< 0 ,意味着在字典中 string1 排在 string2 的前面。
如果 string1.compareTo(string2) > 0 ,意味着在字典中 string1 排在 string2 的后面。
如果 string1.compareTo(string2) == 0 ,意味着 string1 和 string2 是相等的。(该测试是 string1.equals(string2) 的替代形式。)
程序2 字符中比较示例。
class StringTest
{ publicstatic void main(String args[])
{ String str = "This is the firststring.";
booleanresult1 = str.equals("This is the first string.");
booleanresult2 = str.equals("this is the first string.");
booleanresult3 = str.equalsIgnoreCase("this is the first string.");
System.out.println("result1= " + result1);
System.out.println("result2= " + result2);
System.out.println("result3= " + result3);
}
}
程序2的执行结果如下所示。
result1 = true
result2 = false
result3 = true
Java是大小写敏感的。如果s1是"cat"而s2是"Cat",则s1.equals(s2)返回false。
字符可以根据它们在ASCII表中的位置进行比较。需要知道的是所有数字位于所有大写字母之前,所有大写字母又位于所有小写字母之前,空格在所有字符的前面。所以"5"在"R"的前面,"R"又在"a"的前面。两个字符串的比较规则如下:从每个串的最左开始,依次对两个串的对应字母进行字符与字符的比较,直到到达能区分字符串的第一个字符时为止,比如说第k个字符。如果s1的第k个字符排在s2的第k个字符前,则s1先于s2,反之亦然。如果一个字符串是另一字符串的前缀,则较短的字符串先于较***。下面是几个示例。
String s1 = "HOT", s2 ="HOTEL", s3 = "dog";
if (s1.compareTo(s2)< 0)) //true, s1更短
...
if (s1.compareTo(s3)> 0)) //false, "H"排在"d"的前面
不要使用==来测试字符串!与equals()方法不同的是,==判定的是两字符串对象是否是同一实例,即它们在内存中的存储空间是否相同。表达式if (string1 == string2)测试的是string1和string2是否是相同引用。它不测试实际的字符串。使用==来比较字符串可能导致意想不到的结果。
例3 字符串测试。
String s = "oh no!";
String t = "oh no!";
if (s == t) ...
虽然看起来s和t是不同的引用,但测试s==t将返回真。原因是,为了效率,Java对相同的字符串常量只建立一个String对象。这是安全的,因为String对象是不能修改的字符串。
例4 字符串测试。
String s = "oh no!";
String t = new String("oh no!");
if (s == t) ...
这次s==t测试将返回假,因为使用new创建了一个新的对象。本例中s和t是不同的引用!
3. String中的其他方法
Java String类提供了很多方法,除了到目前为止所讨论的构造方法、比较方法和连接运算符+外,还应该知道下列方法。
int length() :返回本串的长度。
String substring(intstartIndex):将本串的子串作为一个新串返回。子串从下标为startIndex的字符处开始,一直到串尾。首字符的下标为0。如果startIndex是负数或大于串的长度,则方法抛出StringIndexOutOfBoundsException。
String substring(intstartIndex, int endIndex):将本串的子串作为一个新串返回。子串从下标为startIndex的字符处开始,一直到endIndex-1。(可以这样来看:startIndex是你想要的首字符;endIndex是你不想要的首字符。)如果startIndex是负数,或endIndex大于串的长度,或startIndex大于endIndex,方法抛出StringIndexOutOfBoundsException。
int indexOf(String str):返回本串中str首次出现的下标。如果str不是串的子串,返回-1。如果str是空串,则方法抛出NullPointerException。