J2SE学习笔记3 — Java基本语法(5)字符串和构建字符串

3.6 字符串

  Java字符串就是Unicode字符序列,Java没有内置的字符串类型,而是在标准Java类库中提供了一个预定义类Stringjava.lang.String)。每个用双引号括起来的字符串(java的字符串字面值)都是String类的一个实例,例如:

  String e = “”;

  String greeting=hello”;

1)提取子串

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

String  greeting=Hello”;

String  s=greeting.substring0,3);//s的值为“Hel

 

String

substring(int beginIndex)
          
返回一个新的字符串,它是此字符串的一个子字符串。

 String

substring(int beginIndex, int endIndex)
          
返回一个新字符串,它是此字符串的一个子字符串。

  substring方法的第一个参数是开始复制的第一个位置。

substring方法的第二个参数是不想复制的第一个位置,例如上例中要复制的位置是从02,不包含3

  substring的工作方式利于计算子串的长度,即字符串s.substring(a,b)的长度为b-a

2)字符串拼接

   Java语言允许使用+号连接两个字符串,例如:

     String s1="hel";

          String s2="lo";

          String s=s1+s2;

          System.out.println(s); //输出hello

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

int s1=13;

      String s2=".jpg";

      String s=s1+s2;

    System.out.println(s);  //输出13.jpg

这种特性也通常用在输出语句中,例如:

     System.out.println(The number is +num)//num可以是int

3)不可变字符串

C/C++不同,String类没有提供用于修改字符串的方法,如果希望将String s=Hello”的内容修改为“HelLO”,不能直接将s的最后两个位置修改为“L”和“O”。如果确实需要修改,只能首先提取需要的字符,然后再拼接上替换的字符串形成一个新的字符串实例,例如

String s="Hello";

s=s.substring(0,3)+"LO";

   System.out.println(s);

由于不能修改java字符串中的字符,所以Java文档中将String类对象成为不可变字符串。不可变字符串虽然降低了字符串修改时的运行效率,但优点是:编译器可以让字符串共享。

 

 

具体的工作方式是:可以想象将各种字符串值存放在公共的存储池中,字符串变量指向存储池中相应的位置,如果复制一个字符串变量,原始字符串与复制的字符串共享相同的字符。

换言之,Java的设计者认为共享带来的高效率远远胜过提取 、拼接字符串所带来的低效率。

一般的程序很少需要修改字符串,更多地是进行字符串的比较,例外的情况就是将源自于文件或键盘的单个字符或较短的字符串汇集成字符串,为此Java提供了一个独立的类“构建字符串”。

Java不同于CJava字符串更像C语言中的char*指针,而不是C语言中的字符型数组char str[]=Hello”;当采用另一个字符串替换str时,Java代码主要进行下列操作:

char* temp=malloc(6) //在“堆”中重新开辟一块内存

strncpytemp,str,3);

strncpytemp+3,“LO”,3);

str=temp

JavaC++string对象都自动地进行内存的分配与回收,不同的是C++的字符串是可修改的。

4)检测字符串是否相等

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

s.equalst

比较st,如果相等返回true,否则返回false。需要注意的是:st可以是字符串变量也可以是字符串常量。例如:“Hello.equalsstr)。

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

“Hello”.equalsIgnoreCase”hello”

  特别注意:一定不能使用= =运算符检测两个字符串是否相等。这个运算符这能确定两个字符串是否放置在同一个位置上,而不是比较两个字符串的内容。

C++string类重载了==运算符以便检测字符串内容的相等性,而Java没有采用这种方式,C程序员从不使用==对字符串进行比较,而使用strcmp函数。JavacompareTo方法与strcmp完全类似,它的声明如下:public int compareTo(String anotherString)例如ifstr.compareTo(“Hello”) == 0

   不过,使用equals更为清晰。

5)代码点与代码单元

    Java字符串由char序列组成,而字符数据类型是一个采用UTF-16编码表示Unicode代码点的代码单元。大多数常用的Unicode字符使用一个代码单元就可以表示,而辅助字符需要一对代码单元表示。

UTF-16使用1621位二进制位表达,即从/u0000 /u10FFFF/u0000/uFFFF表示基本的16位字符,/u10000/u10FFFF表示辅助字符(supplymentary characters)。

 辅助字符由一个高位替代符(high-surrogate )和一个低位替代符(low-surrogate )共同组成。高位替代符使用一个/uD800/uDBFF之间的字符表示;低位替代符使用一个/uDC00/uDFFF之间的字符表示。假设:A代表辅助字符(SC)的码点值; B代表SC的高位替代符的码点(Unicode code point)值; C代表SC的低位替代符的码点值。那么下面的等式成立:A = (B - 0xD800) << 10 + (C - 0xDC00) + 0x10000在将Unicode还原为可阅读字符的时候,当且仅当当前字符时高位替代符,下一字符是低位替代符时,此连续的两个字符被解释为辅助字符。

   Java以独特的风格对字符串中的代码单元计数:字符串中的第一个代码单元位置为0,这种习惯起源于C

    length方法将返回采用UTF-16编码表示的给定字符串所需要的代码单元数量。例如:

    String str=Hello”;

    int n=str.length();//is 5

    要想得到实际的长度,即代码点数量,可以调用:

    int cpCount=str.codePointCount 0str.length());

    调用s.charAt(n)可返回位置n的代码单元,n介于0~s.length()-1之间,例如:

     char first = str.charAt(0); //is ‘H’

     char last = str.charAt(str.length()-1); // is ‘o’

6)字符串API

     JavaString类包含了50多个方法,并且绝大多数都很实用。下面汇总了一部分最常用的方法:

1)字符串比较

boolean equalsObject other

检测字符串相等,如果字符串与other相等,返回true,否则返回false

boolean equalsIgnoreCaseString other

检测字符串相等(忽略大小写),如果相等返回true,否则返回false

int compareToString other

按照字典顺序如果字符串位于other之前返回负数;如果位于other之后返回正数;相同返回0

2)字符串匹配和判断

int length()

返回字符串的长度

char charAtint index

返回给定位置的代码单元,除非对底层的代码单元感兴趣,否则不需要调用这个方法。

boolean startsWithString prefix

如果字符串以prefix字符串开始,返回true

boolean endsWithString suffix

如果字符串以suffix结尾返回true

int indexOfString str

int indexOfString strint fromIndex

int indexOfint cp

int indexOfint cpint fromIndex

返回与字符串str或代码点cp匹配的第一个子串的开始位置,这个位置从索引0fromIndex开始计算,如果在原始串中不存在str,返回-1

int lastIndexOfString str

int lastIndexOfString strint fromIndex

int lastIndexOfint cp

int lastIndexOfint cpint fromIndex

返回与字符串str或代码点cp匹配的最后一个子串的开始位置,这个位置从原始串尾端或fromIndex开始计算。

int  codePointAtint index jdk5.0

返回从给定位置开始或结束的代码点

int  codePointCountint startIndexint endindex jdk5.0

返回startIndexendIndex-1之间的代码点数量,没有配成对的代用字符将计入代码点。

3)字符串处理

String trim()

返回一个新字符串,这个字符串将删除原始字符串头部和尾部的空格。

String substringint beginIndex

String substringint beginIndexint endIndex

返回一个新字符串。这个字符串包含原始字符串中从beginIndex到串尾或endIndex-1的所有代码单元。

String replaceCharSequence oldStringCharSequence newString

返回一个新字符串。这个字符串用newString代替原始字符串中所有的oldString。可以用StringStringBuilder对象作为CharSequence参数。

String toLowerCase()

返回一个新字符串,这个字符串将原始字符串中所有大写字母改成小写字母。

String toUpperCase()

返回一个新字符串,这个字符串将原始字符串中的所有小写字母改成大写字母。

具体内容可参阅API文档。

3.7 构建字符串

有些时候,需要由较短的字符串构建一个长的字符串,采用String对象时每次连接字符串其实都是在构建一个新的String对象,既耗时又浪费空间。使用StringBuilder类可避免这个问题的发生。

使用StringBuilder类进行字符串连接的步骤:

u  首先,构建空的字符串构建器:StringBuilder bulder=new StringBuilder();

u  每次需要添加内容时,调用append方法。

builder.appendch);// ch is a single character

builder.appendstr);// str is a string

u  在需要构建字符串时可以调用toString方法,就可以得到一个String对象。

String comString=builder.toString();

注:

   Jdk5.0引入了StringBuilder类,它的前身是StringBuffer,其效率略低,但允许采用多线程的方式执行添加或删除字符的操作。如果所有字符串在一个单线程中(通常情况)编辑,则应该用StringBuilder替代它。

   这两个类的API是相同的。

²  构建字符串的常用API

StringBuilder()

构造方法:构造一个空的字符串构建器。

int length()

返回构建器或缓冲器中的代码单元数量。

StringBuilder  appendString str

StringBuilder  appendchar c

追加一个字符串(或字符)并返回this

void setCharAtint ichar c

将第i个代码单元设置为c

StringBuilder  insertint offsetString str

StringBuilder  insertint offsetChar  c

offset位置插入一个字符串(或字符)并返回this

StringBuilder  deleteint startIndexint endIndex

删除偏移量从startIndexendIndex-1的代码单元并返回this

String   toString()

返回一个与构建器或缓冲器内容相同的字符串

StringStringBuilder使用方法示例:

/**

 * desc:StringStringbuilder类示例(纯举例,无实际意义)

 * @version 0.1 2011-5-4

 * @author W&A

 */

public class FirstSample

{

       public static void main(String[] args)

       {

             

              // 主程序:构造测试url字符串,调用字符串检测的静态方法

              String url1=" http://www.Br.com/news/xxx/admin/action.jsp?id=2 "; 

              String url2=DealStr.dealStr(url1);

              System.out.println("原始字符串:"+url1);

              System.out.println(url2);

       }

}

/*

 *  URL字符串处理类—对url域名和目录进行分离

 *  检测内容:只能访问特定网站,目录不能包含admin

 */

class DealStr

{

   public static String dealStr(String url)

   {  

          String originUrl=null;

          StringBuilder strbuf=new StringBuilder(); 

          String tempStr=null;

 

       //(1) url预处理,去掉“http://”前缀及多余空白字符

          originUrl=url.trim();

          if( ! originUrl.startsWith("http://"))

          {

             strbuf.append("url格式字符串");

                return strbuf.toString();

          }

          int beginpos="http://".length();

          originUrl=originUrl.substring(beginpos);//format: 域名/目录名/../文件名?参数=参数值

          originUrl=originUrl.toLowerCase(); //全部转换为小写以便比较

        

          //(2) 提取主机域名并检查

          beginpos=originUrl.indexOf('/');

          String host=originUrl.substring(0,beginpos);

       if(!host.equals("www.br.com"))

          {

             strbuf.append("不是本站点域名/n检测完毕,出现错误");

                return strbuf.toString();

          }

          strbuf.append("访问站点:"+host+"/n");

      

          //(3) 提取目录并检测是否含有admin,如果含有admin报错并屏蔽目录显示

          int lastpos=originUrl.lastIndexOf('/');

       if (beginpos<lastpos) //有目录存在 

          {

          tempStr=originUrl.substring(beginpos+1,lastpos+1);//format:目录1/目录2/../目录n/

                StringBuilder tempbuf=new StringBuilder();

                tempbuf.append(tempStr);

                int pos=tempbuf.indexOf("/"); //StringBuilder类只有indexOf(String str)方法

                String dirStr=null;

                int bufpos=strbuf.length(); //保存当前strbuf的长度

                strbuf.append("资源目录:");

                 while(pos!=-1) //有多层目录存在

              {

                  dirStr=(tempbuf.toString()).substring(0,pos);

                        if(dirStr.equals("admin"))

                        {

                           strbuf.delete(bufpos,strbuf.length());

                              strbuf.append("资源目录中含非法的admin目录/n检测完毕,出现错误");

                              return strbuf.toString();

                        }

                        strbuf.append(dirStr+"/");

               //修正目录串和pos

                  tempbuf=tempbuf.delete(0,pos+1);

                        pos=tempbuf.indexOf("/");

              }

                 strbuf.append("/n");

          }

          //正常返回

          strbuf.append("检测完毕,没有错误");

       return strbuf.toString();

   }

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值