字符串时编程中经常要使用到的数据结构。它是字符的序列,从某种程度上来说有些类似于字符的数组。在java这个面向对象的语言中,字符串,无论是常量还是变量,都是用类的对象来实现的。
程序中需要用到的字符串可以分为两大类:
(1) 一类时创建之后不再做修改和变动的字符串常量;
(2) 另一类时创建之后允许再做修改和变化的字符串变量。
对于字符串常量,由于程序中经常需要对它做比较、搜索之类的操作,所以通常把它放在一个具有一定名称的对象之中,由程序对该对象完成上述操作。在java中,存放字符串常量的对象属于String类。对于字符串变量,由于程序中经常需要对它做添加、插入、修改之类的操作,所以一般都存放在StringBuffer类的对象中。
1 String类
字符串常量用String类的对象表示。在前面的程序中,以多次使用了字符串常量。这里首先强调一下字符串常量与字符常量不同。字符常量是用单引号括起的单个字符,例如’a’,’\n’等。而字符串常量是用双引号括起的字符序列,例如”a”,”\n”,”Hellow ”等。Java中的字符串常量,表面上与其他语言中的字符串常量没有什么不同,但在具体实现上却有较大的差异。Java的字符串常量,通常是作为String类的对象存在,由专门的属性来规定它的长度。实际上,对于所有用双引号括起的字符串常量,系统会把它创建一个无名的String类型对象。
创建字符串常量string对象
由于string类的对象表示的是字符串常量,所以一般情况下,一个String字符串一经创建,无论其长度还是其内容,都不能够再更改了。因而,在创建String对象时,通常需要向String类的构造函数传递参数来指定所创建的字符串内容。下面简单列出string类的构造函数及其使用方法。
pulic String()
这个构造函数用来创建一个空的字符串常量。
public String(String value)
这个构造函数利用一个已经存在的字符串常量创建一个新的String对象,该对象的内容与给出的字符串常量一致。这个字符串常量可以是另一个String对象,也可以是一个用双引号括起来的直接常量。
public string(stringBuffer buffer)
这个构造函数利用已经存在的字符数组的内容初始化新建的String对象。
创建string对象与创建其他类的对象一样,分为对象的声明和对象的创建两步。这两步可以分成两个独立的语句,也可以在下一个语句中完成。
例如下面的句子仅声明一个String对象s:
String s;
此时s的值为null,要想使用s ,还必须为它开辟内存空间。
String s=new String ("ABC");
这样,通过调用上面的第二个构造函数,字符串s被置为"ABC"。上述两个语句也可以合并成一个语句如下:
String s=new String ("ABC");
在java中,还有一种非常特殊而常用的创建String对象的方法。这种方法直接利用双引号括起来的字符串常量为新的String对象“赋值”:
String s="ABC";
其实这里的“赋值”只是一种特殊的省略写法,前面已经提到,java系统会自动为每一用双引号括起来的字符串常量创建一个String对象,所以这个语句的实际含义与效果与前一个句子完全一致。
2、字符串产量的操作
String类中所包含的字符串常量的操作很多,如:求字符串的长度。具体方法如下:
public int length();
用它可以获得当前字符串对象中字符的个数。例如运行下面的代码:
String s="Hello!"
System.out.println(s.length());
屏幕将显示6,因为字符串"Hello!"的长度为6。需要注意的是在java中,因为每个字符都是占用16个比特的Unicode字符,所以汉字与英文或其他符号相同,也只用一个字符表示就足够了。如果把上面的字符串替换为“近来身体好吗”,则字符串的长度不变,仍然是6。
3、判断字符串的前缀和后缀
public boolean startsWith(String prefix);
public boolean endsWith(String prefix);
这两个方法可以分别判断当前字符串的前缀和后缀是否是字符子串。
区分字符串的前缀及后缀在某些情况下是非常有用的操作。
又例如,居民身份证号码的最后一位代表了居民的性别,奇数为男性,偶数为女性。假设String对象s是某位居民的身份证号码,则下面语句将判断出它的性别:
if(s.endsWith("0")||s.endsWith("2")||s.endsWith("4")||s.endsWith("6")||s.endsWith("8"))
{ System.out.println("此人是女性");
}
startWith和endWith这两个方法的一个突出优点是不限制所判断的前缀、后缀的长度。例如前一个例子中若需判断的前缀从“6278”变换到“627”,则原方法仍然有效,不需要更改程序。
4、字符串中单个字符的查找
public int indexOf(int ch);
public int indexOf(int ch,int fromIndex);
上述两个方法查找当前字符串中某个特定字符出现的位置。第一个方法查找字符ch在当前字符串中的一次出现的位置,即从头向后查找,并返回字符ch出现的位置。如果找不到则返回-1。例如下面的语句将把值0赋给整型量idx:
String s="java是面向对象的语言,javaScript是脚本语言";
int idx=s.indexOf((int)'J');
第二个方法查找字符ch时,在当前字符串中自fromIndex位字符之后向后查找,并返回该字符首次出现的位置。下面语句将查找处指定字符在字符串中的所有出现位置:
String s="java是面向对象的语言,javaScript是脚本语言";
int i=-1;
do{
i=s.indexOf((int)'a',i++);
system.out.print(i+"\t");
}while(i!=-1);
运行结果是:1 3 14 16 -1
下面的两个方法也是查找字符串中单个字符的方法,不同的是它们从字符串的结尾向字符串的开始部分查找,这里就不再举例了。
public int lastIndexOf(int ch);
public int lastIndexOf(int ch,int fromIndex);
5、字符串中子串的查找
public int indexOf(string str);
public int indexOf(string str,int fromIndex);
public int lastIndexOf(string str);
public int lastIndexOf(string str,int fromIndex);
在字符串中查找字符子串与在字符串中查找单个字符非常相似,也有四种可供选择的方法,它就是把查找单个字符的四个方法中指定的字符ch换成了指定字符串str。下面的例子从字符串尾部向前,顺序查找所有子串出现的位置:
String s="java是面向对象的语言,javaScript是脚本语言";
String sub="语言";
for (int i=s.length();i!=-1){
i=s.lastIndexOf(sub,i-1);
system.out.print(i+"\t");
}
上述程序运行的结果是:26 10 -1
另外,还定义有获取字符串中的某个字符的方法:
public char charAt(int index);
这个方法获取当前字符串第index个字符并返回这个字符(index从0算起)。
6、比较两个字符串
public int conpareTo(string anotherString);
public boolean equals(Object anObject);
public boolean equalsIgnoreCase(string anotherString);
String类中有三个方法可以比较两个字符串是否相同。方法equals是重载Object类的方法,它将当前字符串与方法的参数列表中给出的字符串乡比较,若两字符串相同,则返回其真值,否则返回假值。方法equalsIgnoreCase与方法equals的用法相似,只是它比较字符串时不计字母大小写的差别。
例如,在下面的语句中,分别用equals方法和equalsIgnoreCase方法比较两字符串,则在第一语句中由于区分大小写,所以比较结果为假,而在第二个语句中由于不区分大小写,所以比较结果为真:
string s1="Hello!World"; s2="hello!world";
boolean b1=s1.equals(s2);
boolean b2=s1.equalsIgnoreCase(s2);
比较字符串的另一个方法是compareTo(),这个方法将当前字符串与一个参数字符串乡比较,并返回一个整型量。如果当前字符串与参数字符串完全相同,则compareTo()方法返回0;如果当前字符串按字母序大与参数字符串,则compareTo()方法返回一个大于0的整数;反之,若compareTo()方法返回一个小于0的整数,则说明当前字符串按字母序小与参数字符串。
在下面的例子中,compareTo比较了三对字符串。
String s="abc",s1="aab",s2="abd",s3="abc";
int i,j,k;
i=s.compareTo(s1);
j=s.compareTo(s2);
k=s.compareTo(s3);
语句执行的结果是分别给i,j,k三个变量赋值1,-1,0。
7、连接字符子串
public String concat(String str);
这个方法将参数字符串连接在当前字符串的尾部,并返回这个连接而成的长字符串,但是当前字符串本身并不改变。如下面的例子:
String s="Hello!";
System.out.println(s.concat("World!"));
System.out.println(s);
运行结果是:
Hello!World! //连接后的新字符串
Hello! //原字符串没有改变
StringBuffer
java中用来实现字符串的另一个类是 StringBuffer类,与实现字符串常量的String类不同,StringBuffer类的对象可以扩充和修改的字符串变量。
(1) 创建字符串变量-- StringBuffer对象
由于 StringBuffer表示的事可扩充、修改的字符串,所以在创建 StringBuffer类的对象时并不一定要给出初值。 StringBuffer
类的构造函数有以下几个:
public StringBuffer();
public StringBuffer(int length);
public StringBuffer(String str);
第一个函数创建了一个空的 StringBuffer对象。第二个函数给出了新建的 StringBuffer对象的长度,第三个函数利用一个已经存在的字符串String对象来初始化StringBuffer对象。
下面语句是用三种不同的方法创建字符串的例子。
StringBuffer MyStrBuff1=new StringBuffer();
StringBuffer MyStrBuff2=new StringBuffer(5);
StringBuffer MyStrBuff3=new StringBuffer("Hello,Guys!");
需要注意的是,其中第一个对象MyStrBuff1并没有相应的内存单元,需扩充之后才能使用。
(2) 字符串变量的扩充、修改与操作
StringBuffer类有两组用来扩充其中所包含的字符的方法,分别是:
public StringBuffer append(参数对象类型 参数对象名);
public StringBuffer insert(int 插入位置,参数对象类型 参数对象名);
append方法将指定的参数对象转化成字符串,附加在StringBuffer字符串之后,而insert方法则在指定的位置插入给出的参数对象所转化而得的字符串。附加或插入的参数对象可以使各种数据类型的数据,如int,double,char,String等。参看下面的例子:
StringBuffer MyStrBuff1=new StringBuffer();
MyStrBuff1 append("Hello,Guys!");
System.out.println(MyStrBuff1.toString());
MyStrBuff1.insert(6,30);
System.out.println(MyStrBuff1.toString());
上述执行的结果是:
Hello,Guys!
Hello,30 Guys!
需要注意的是,若希望StringBuffer在屏幕上显示出来,则必须首先调用toString方法把它变成字符串常量,因为PrintStream的方法println()不接受StringBuffer类型的参数。
StringBuffer还有一个较有用的方法来修改字符串:
public void setCharAt(int index,char ch);
这个方法可以将指定位置的字符用给定的另一个字符来替换。例如下面的语句将愿意为“山羊”的字符串变成“外套”:
StringBuffer MyStrBuff=new StringBuffer("goat");
MyBuff.setCharAt(0,'c');
(3) 字符串的赋值和加法
字符串是经常使用的数据类型,为了编程方便,java编译系统中引入了字符串的加法和赋值。
参看下面的例子:
String MyStr="Hello,";
MyStr=MyStr+"Guys!";
这两个语句出看似乎有问题,因为String是可变的字符串常量,实际上它们是合乎语法规定的,分别相当于:
String MyStr=new StringBuffer().append("Hello").toString();
MyStr=new StringBuffer().append(MyStr).append("Guys!").toString();
由于这种赋值和加法的简便写法非常方便实用,所以在实际编程中用的很多。
Java Application命令行参数
Java Application是用命令行来启动的,命令行参数就成为向Java Application传入数据的常用而有效的手段。现通过下例来考察如何使用命令行参数。
见例程UseComLParameter.java
该例的功能是从命令行利用命令行参数读入两个整数,再把它们相乘后输出。假设将上述程序保存为一个 UseComLParameter.java文件,经编译后生成 UseComLParameter.class文件,则执行这个程序的命令行应该是如下格式:
java UseComLParameter 52 -4
这里,java是用来运行字节码的java解释器,UseComLParameter是所运行的字节码文件名(即所执行的类名),52和-4分别是两个命令行参数。
可以看出,java的命令行参数跟在命令行主类名的后面,参数之间用空格分隔。如果命令行参数本身就带有空格,则可以用双引号将整个参数括起来以示区别,例如“a dog”就是一个完整的命令行参数。
Java Application程序中用来接受命令行参数的数据结构的是main()方法的参数args[],这个参数是一个字符串数组,其中的每个元素都是一个字符串,这些字符串来自于用户与类名同时输入的命令行参数,每个字符串保存一个命令行参数供程序使用,用户输入了几个命令行参数,数组args[]就有几个元素。另外需要注意的是,所有命令行参数都以字符串String类型的对象形式存在,如果希望把参数作为其他类型的数据使用,则还需要作相应的类型转换。
可见,命令行参数是提供该整个程序的参数,每次运行时使用不同的命令行参数,就有不同的运行结果;使用命令行参数可以提高程序的灵活性和适应性。不过在使用命令行参数时要注意数组越界问题,程序运行是系统将自动检查用户输入了多少个命令行参数并逐个地保存在args[]中,但是如果程序不检查用户到底数入了多少个命令行参数而直接访问args[]某下标地数组元素,则可能造成数组越界异常。