Java基础—字符串

  事实上,Java是没有内置的字符串类型的,而是在标准Java类库中提供了一个预定义类String。每个用双引号括起来的字符串都是String类的一个实例:

String str = ""; // an empty string
String greeting = "Hello";

1.子串

  String类的substring方法可以从一个较大的字符串提取出一个子串。例如:

String greeting = "Hello";
String str = greeting.substring(0,3); //str is "Hel"

创建了一个由字符"Hel"组成的字符串。

  substring方法的第二个参数是不想复制的第一个位置。这里要复制的位置为0、1和2(从0到2,包括0和2)的字符。在substring中下标从0开始计数,直到3为止,但不包含3(就像数学中的区间表示其范围【0,3))。

  substring的工作方式有一个优点:容易计算子串的长度。字符串s.substring(a,b)的长度为b-a。例如,子串"Hel"的长度为3-0=3。

2.拼接

  与绝大多数的程序设计语言一样,Java语言允许使用+号连接(拼接)两个字符串。

String str = "str";
String jack = "jack";
String message = str + jack; //message is "strjack"

  上述代码将"strjack"赋给变量message(注意,单词之间没有空格,+号按照给定的次序将两个字符串拼接起来)。

  当将一个字符串与一个非字符串的值进行拼接时,后者会被转换成字符串(任何一个Java对象都可以转换成字符串)。例如:

int age = 18;
String rating = "PG" + age; // rating is "PG18"

  我们可以得到rating的值为"PG18"。这种特性通常用在输出语句中。例如:

System.out.println("The answer is" + rating);

  这是一条合法的语句,并且将会打印出所希望的结果(The answer is PG18),如果单词is后面加了一个空格,输出时也会加上这个空格。

3.不可变字符串

  查看源码可以知道,String类是final修饰的不可变类:

public final class String implements java.io.Serializable, Comparable<String>, ChaSequence{...}

  由此可见,String类没有提供用于修改字符串的方法。但是如果希望将greeting的内容修改为"Help!",不能直接的将greeting的最后两个位置的字符修改为"p"和"!"。这对于C程序员来说,将会感到无从下手。如何修改这个字符串呢?在Java中实现这个操作非常容易。首先提取需要的字符,然后再拼接上替换的字符串:

greeting = greeting.substring(0,3) + "p!"; //greeting is "Help!"

  由于不能修改Java字符串中的字符,所以在Java文档将String类对象称为不可变字符串,如同数字3永远是数字3一样,字符串"Hello"永远包含字符H,e,l和o的代码单元序列,而不能修改其中的任何一个字符。当然,可以修改字符串变量greeting,让它引用另外一个字符串,这就如同可以将存放3的数值变量改成存放4一样。

  有人会问,这样做是否会降低运行效率呢?看起来修改一个代码单元要比创建一个新的字符串更加简洁。答案是:也对,也不对。的确,通过拼接"Hel"和"p!"来创建一个新字符串的效率确实不高。但是,不可变字符串却有一个优点:编译器可以让字符串共享。

  如果不是很清楚,可以想象将各种字符创存放在公共的存储池中。字符串变量指向存储池中相应的位置。如果复制一个字符串变量,原始字符串与复制的字符串共享相同的字符。

  总而言之,Java的设计者认为共享带来的高效率远远胜过于提取、拼接字符串所带来的低效率。查看一下写过的程序会发现:很少需要修改字符串,而是往往需要对字符串进行比较(有一种例外情况,将源自于文件或键盘的单个字符或较短的字符串汇集成字符串。为此,Java提供了一个独立的类,在下面"构建字符串"中将详细的给予介绍)。

4.检测字符串是否相等

  可以使用equals方法检测两个字符串是否相等。对于表达式:

s.equals(t)

  如果字符串s与字符串t相等,则返回true;否则,返回false。需要注意,s与t可以是字符串变量,也可以是字符串常量。例如,下面表达式是合法的:

"Hello".equals(greeting)

  要想检测两个字符串是否相等,而不区分大小写,可以使用equalsIgnorCase方法:

"Hello".equalsIgnorCase(greeting)

  注意:一定不能使用 == 运算符检测两个字符串是否相等!这个运算符只能确定两个字符串是否放在同一个位置上(栈区存放的是引用地址,其实堆区存放的才是实际的值,而 == 运算符比较的就是栈区里面的值)。当然,如果字符串存放在同一个位置上,它们必然相等。但是,完全有可能将内容相同的多个字符串的拷贝位置放在不同的位置上。

String greeting = "Hello"; //initialize greeting to a string
if (greeting == "Hello")...
    //probably true
if (greeting.substring(0,3) == "Hel")...
    //probably false

  如果虚拟机始终将相同的字符串共享,就可以使用 == 运算符检测是否相等。但实际上只有字符串常量是共享的,而+或者substring等操作产生的结果并不是共享的。因此,千万不要使用 == 运算符测试字符串的相等性,以免在程序中出现糟糕的bug。从表现上看,这种bug很像随机产生的间歇性错误。

5.构建字符串

  有些时候,需要由较短的字符串构建字符串,例如,按键或来自文中的单词。采用字符串连接的方式达到此目的的效率比较低。每次连接字符串,都会构建一个新的String对象,既耗时,又浪费空间。使用StringBuilder类就可以避免这个问题的发生。

  如果需要用许多小段的字符串构建一个字符串,那么应该按照下列步骤进行。首先,构建一个空的字符串构造器:

StringBuilder builder = new StringBuilder();

  当每次需要添加一部分内容时,就调用append方法:

builder.append("ch"); //appends a single character
builder.append("str"); //appends a string

  在需要构建字符串时就调用toString方法,将可以得到一个String对象,其中包含了构建器中的字符序列。

String completedString = builder.toString();

  注意:在JDK5.0中引入StringBuilder类。这个类的前身是StringBuffer(基于线程安全),它的效率略微有些低,但允许采用多线程的方式执行添加或删除字符的操作。如果所有字符串在一个单线程中(通常都是这样)编辑,则应该用StringBuilder替代它。

猜你喜欢

转载自www.cnblogs.com/JackWeTa/p/11425635.html
今日推荐