`
liuwei1981
  • 浏览: 752596 次
  • 性别: Icon_minigender_1
  • 来自: 太原
博客专栏
F8258633-f7e0-30b8-bd3a-a0836a5f4de5
Java编程Step-by...
浏览量:156173
社区版块
存档分类
最新评论

87.String类

 
阅读更多

在Java中,使用String和StringBuffer来表示封装了一系列字符的对象,习惯上,将它们称为“字符串”。

 

1 String


String 类包含了一个不可改变(immutable)的字符串。一旦一个String实例被创建,包含在这个实例中的内容(“字符串”)不可被更改,直至这个对象被销毁。因此,指向String对象的变量实质上是一个常量,String对象也被称为常量对象。

 

创建一个String对象有很多种方法,但最常见的方法是将一个字符系列当作参数给String的构造器来创建一个String 实例,如下:
 String s = new String(“abcdefgh”);


但也可以使用一种更常见的方式来定义一个String对象:
 String s = “abcdefgh”;


在这条语句中,Java将为字符串“abcdefgh”隐式地创建一个String对象。


如果想建立一个空字符串,也可以相应的采用两种方式:
 String s = new String();



 String s = “”;


请注意空字符串(””)和null的区别。空字符串表示的是这个String对象内容为空,而空String对象(null)表示这个String类的变量不指向任何的String实例。

在String类中,定义了很多的方法,通过这些方法,可以创建新的字符串。下面我们会对一些常用的方法做一些简单的介绍。

 

String的“不可更改”含义

 

 

在前面我们说过,String类是不可更改的(immutable),那么什么是不可更改呢?

 

 


在String类中,不可更改的意思是,只要生成了一个String实例,那么,它里面的内容是不能被更改的。虽然String有很多的方法,但是没有一个方法可以用来改变它的内容。


我们来看一个例子。

 

public class ImmutableString{
 public static void main(String[] args){
  String a = "abcde";
  System.out.println("a = "+a+" //1");      //1
  String b = a.toUpperCase();
  System.out.println("a = "+a+" //2");      //2
  System.out.println("b = "+b+" //3");      //3
 }
}


在这个类ImmutableString的方法main()中,首先定义了一个String对象a,它的内容为“abcde”,然后在//1处将它打印出来,毫无疑问,此时将打印出“abcde”,然后,调用String类的一个方法toUpperCase(),,它将a中的字符串内容全部变为大写后返回给另一个String变量b,随后,再在//2处将a打印出来,在//3处将b打印出来。在//2处将打印什么值呢?如果toUpperCase()修改的是实例a中的内容,那么,此处应该打印出全部大写的“ABCDE”,而在//3处,毫无疑问,应该是全部大写的“ABCDE”,到底结果如何呢?


编译并运行这个程序,将得到如下的输出:
a = abcde       //1
a = abcde       //2
b = ABCDE       //3


这就说明了,toUpperCase()方法并没有改变a中的内容,而只是将a中的内容全部转化成大写后新生成了一个String对象给变量b。

 

创建String细节

 

 

我们在前面说过,通过下面的方式之一,就可以创建一个String对象:
String s1 = new String(“abc”);
String s2 = “abcde”

 

 


那么,这两种创建字符串的方式有没有区别呢?
我们来看一个例子。

public class StringEqual{
 public static void main(String[] args){
  String s1 = new String("Test"); //1
  String s2 = new String("Test"); //2
  
  String s3 = "Test"; //3
  String s4 = "Test"; //4
  
  System.out.println("s1 == s2? Answer:"+(s1 == s2)); //5
  System.out.println("s1 equals s2? Answer:"+s1.equals(s2)); //6
  
  System.out.println("s3 == s4? Answer:"+(s3 == s4)); //7
  System.out.println("s3 equals s4? Answer:"+s3.equals(s4)); //8 
 }
}


在这个例子中,通过new操作符来创建了两个String对象s1和s2,通过直接指定字符串值的方法创建了s3和s4两个String对象,然后,我们来看一下它们是否相等。在这里我们使用了“==”和“equals()”方法两种方式来比较:“==”比较的是两个变量是否指向同一个对象引用,而“equals()”方法比较的是对象内容是否相等。


编译并运行这个程序,将得到如下的输出:
s1 == s2? Answer:false
s1 equals s2? Answer:true
s3 == s4? Answer:true
s3 equals s4? Answer:true


对于s1和s2的比较结果,完全在我们的意料之中:s1和s2指向的是两个不同的对象,而s1和s2的内容是相等的。但对于s3和s4,就让我们疑惑了,为什么s3==s4的比较居然相同?它们是指向同一个对象么?


答案是肯定的:如果通过直接指定字符串值的方法来创建String对象,它将保存在内存的一个“字符串池”中,而如果“池”中已经存在同样内容的字符串,则将不生成新的字符串,而是直接使用这个已经存在的字符串对象。所以,在行//4中,只是将s4这个变量指向已经存在的对象,也就是s3所指向的对象。因此,在这个时候s3和s4指向的是同一个对象,表达式“s3 == s4”也就等于true了。


对于使用new操作符来创建String对象,无论内存中是否已经存在相同内容的对象,它都会在内存中新建一个新的对象。


从上面的分析我们可以得到一个结论:除非必须,不要使用new操作符来创建字符串对象。在进行字符串内容值的比较的时候,应该使用equals()方法而应该避免使用“==”运算符,除非你能确定所有的String对象是用直接赋值而非用new操作符创建。


除了字符串变量可以使用equals()方法外,字符串常量也可以使用它来和其他的字符串数据比较:
"Test".equals(s1);


上面的表达式是合法的。
 在使用equals()进行字符串比较的时候,它是区分大小写的。除了equals()方法外,Java String还提供另外一个不区分大小写的比较方法:equalsIgnoreCase(),除了它不区分大小写以外,用法和equals()一样。

 

String常用的方法


String提供了很多的方法,下面列出了比较常用的方法:


public String concat(String str)---将str的内容连接到当前字符串的尾部,组成新的String对象并返回。其中str的值不能为null,否则运行出错。此外,如果str的长度为0,则不创建新对象,而直接返回当前对象的句柄。


public String replace(char oldChar, char newChar)---将当前字符串对象中出现的所有oldChar替换为newChar,组成新的String对象并返回。如果oldChar一次也未出现过,则不创建新对象,而直接返回当前对象的句柄。


public String substring(int beginIndex)---从当前字符串中截取子串,范围从beginIndex开始(包括索引为beginIndex的字符)直到结尾,组成新的String对象并返回。注意在字符串中的索引是从0开始的。如果beginIndex=0,则不创建新对象,而直接返回当前对象的句柄。


public String substring(int beginIndex, int endIndex)---与前者类似,截取范围从beginIndex开始直到endIndex。


public String toLowerCase()---将当前字符串中所有字符转换为小写形式,组成新的String对象并返回。如果当前字符串中不含非小写形式的字符,则不创建新对象,而直接返回当前对象的句柄。


public String toUpperCase()---与toLowerCase()相反,将当前字符串中所有的字符转换成大写形式,组成新的String对象返回。


public String trim()---删除当前字符串前后的空格符,组成新的String对象并返回。如果当前字符串中不含前后空格符,则不创建新对象,而直接返回当前对象的句柄。


public boolean startsWith(String prefix)---如果prefix是当前字符串的前缀,则返回true,否则返回false。

public boolean startsWith(String prefix, int toffset)---判断prefix是否是当前字符串从下标toffset开始的子串。


public boolean endsWith(String suffix)---如果prefix是当前字符串的后缀,则返回true,否则返回false。


public int indexOf(int ch)---返回字符(char)ch在当前字符串中第一次出现的位置。如未找到则返回-1。

public int indexOf(int ch, int fromIndex)---返回(char)ch在当前字符串中位置fromIndex以后第一次出现的位置。


public int indexOf(String str)---返回子串str在当前字符串中第一次出现的位置。如未找到则返回-1。


public int indexOf(String str, int fromIndex)---返回子串str在当前字符串中位置fromIndex以后第一次出现的位置。


public int lastIndexOf(String str)/ lastIndexOf(String str,int fromIndex) / lastIndexOf(int ch,int lastIndex) / lastIndexOf(int ch) ---与indexOf方法类似,返回特定字符或子串在当前字符串中(或指定位置以后)最后一次出现的位置。


public boolean equals(Object anObject)---判断当前String对象与参数anObject指定的对象是否等价。只有当anObject也是String类型,且其内容与当前对象相同时返回true,否则返回false。


public boolean equalsIgnoreCase(String anotherString)---与equals()方法类似,但忽略大小写的差异。


public char charAt(int?index)---返回字符串中下标为index处的字符。其中index的取值范围是0~length -1。


public int length()---返回字符串的长度,即字符串中字符的个数。


2 StringBuffer


和String相反,StringBuffer表示一个内容可变的(mutable)字符系列。通过StringBuffer的append()、insert()、reverse()、setCharAt()、setLength()等方法,可以对这个字符串中的内容进行修改。

 

常用的方法

 

 

 

public StringBuffer append(…)---将参数转换为字符串类型,再追加到当前字符串缓冲区的尾部。此方法针对各种数据类型的参数进行了多次重载,如int、char等简单类型,以及String以及Object等引用类型。

 

 

public StringBuffer insert(int offset, …)---将参数转换为字符串类型,再插入到当前缓冲区的指定位置。


public StringBuffer reverse()---将当前缓冲区中的所有字符前后互换,生成一个新的StringBuffer对象。


public void setCharAt(int index, char ch)---将缓冲区中指定位置的字符替换为参数所指定的字符ch


public int length()---返回当前缓冲区中包含的字符数


public int capacity()---返回当前缓冲区的容量大小

 

提示:
 StringBuffer类是线程安全的。在JDK5.0中,新增了一个和StringBuffer对应的StringBuilder类,这个类和StringBuffer具有相同的方法,因此,对StrngBuffer的讨论也基本适用于StringBuilder类。但是,StringBuilder和StringBuffer不同的地方在于,它是非线程安全的类,但它的优势在于,因为少了很多同步操作,在效率上会高于StringBuffer类。因此如果不涉及多线程操作,可以考虑使用StringBuilder来提高方法的执行效率。


3 用于连接两个String的“+”和StringBuffer的append()

 

 

 

在第四章4.1.8节,我们曾经介绍过,在Java中,为了运算方便,对运算符“+”进行了重载,使得它可以用于连接两个String字符串。例如:
String s1 = "Hello";
String s2 = "World";
String s3 = s1 + s2;

 

 


这个时候,s3的内容为“HelloWorld”。甚至,我们还可以将上面的代码写成如下的样子:
String s1 = "Hello";
String s2 = "World";
s1 = s1 + s2;      //也可写成s1 += s2;


此时,s1的内容也为“HelloWorld”,那么,既然String是不可变的,为什么在这里它的内容发生改变了呢?这是因为,原来s1所指向的那个“Hello”的对象引用已经被“抛弃”了,而s1重新指向了一个新的字符串对象引用“HelloWorld”。

 

而在StringBuffer类中,可以通过它的一个方法append()来实现类似的功能:


StringBuffer sb1 = new StringBuffer("Hello");
StringBuffer sb2 = new StringBuffer("World");
sb1.append(sb2);


此时,sb1中的内容已经变成了“HelloWorld”了。如果需要得到String类型的字符串数据,使用StringBuffer的toString()方法就可以了:
sb1.toString();


下面是完整的代码:

public class TestPlus{
 public static void main(String[] args){
  String s1 = "Hello";
  String s2 = "World";
  s1 += s2;
  
  StringBuffer sb1 = new StringBuffer("Hello");
  StringBuffer sb2 = new StringBuffer("World");
  sb1.append(sb2);
  sb1.toString();
 } 
}

 

既然这两种方法都可以用来进行字符串的连接,那么,用哪种方式比较好呢?


从效率上来说,String的“+”操作劣于StringBuffer的append()方法,这是因为在进行“+”操作时,实际上还是需要将String转换成StringBuffer再使用append()方法进行连接(在JDK5中通常是转换成StringBuilder),最后使用StringBuffer的toString()来转回String。如果从编程习惯上考虑,“+”要优于append(),比如,我们看一下如下的代码:
String s1,s2,s3,s4,r1,r2;
s1 = "This";
s2 = " is";
s3 = " another";
s4 = " day!";

r1 = s1+s2+s3+s4;       //1

StringBuffer sb1 = new StringBuffer("");
r2 = sb1.append(s1).append(s2).append(s3).append(s4).toString();    //2


//1和//2处实现的功能是一样的,但显然,//1处的代码清晰易读,而//2处的代码就不那么容易看懂了。

分享到:
评论

相关推荐

    jspsmartupload上传下载,已修改过源代码!

    87. newFile.setStartData(m_startData); 88. newFile.setEndData(m_endData); 89. m_files.addFile(newFile); 90. } else 91. { 92. /** 93. * 原来的代码 94. * String value = new String(m_...

    Java邮件发送

    用于Java的邮件发送的一个类方法 Java邮件发送类 这是第一部分第一个类:MailSenderInfo.java 1. package com.util.mail; 2. /** 3. * 发送邮件需要使用的基本信息 4. */ 5. import java.util.Properties; 6. ...

    Java 面试宝典

    32、是否可以继承 String 类? ....................................................................................... 24 33、String s = new String("xyz");创建了几个 String Object? 二者之间有什么区别? ...

    spring3.1中文参考文档

    spring3.1中文参考文档,南磊翻译,现在有4章,目录如下: 第一部分 Spring framework概述.......................................................................................................................

    JAVA程序设计教程

    目录 引言 ...................................................................................................................................... I 第一章程序和程序设计 ...............................

    C++良好的编程风格.pdf

    2.8 类的版式 ..................................................................................................................21 第 3 章 命名规则........................................................

    高质量c++编程

    2.8 类的版式................................................................................................................ 21 第3 章 命名规则...........................................................

    TCL脚本语言编程

    VIVADO经常使用TCL脚本对FPGA进行调试,通过JTAG转AXI对内部模块进行控制,但是TCL语言书籍比较少,这边是一个英文的TCL语言学习书籍. 第 1 章. TCL基本知识...........................................................

    高质量C _C编程指南

    9.6 示例:类STRING 的拷贝构造函数与赋值函数................. 73 9.7 偷懒的办法处理拷贝构造函数与赋值函数.......................... 75 9.8 如何在派生类中实现类的基本函数............................. 75...

    c#3.0语言规范高清PDF

    1.6 类和对象 ................................................................................................................................................... 12 1.6.1 成员 ............................

    高质量C++C 编程指南

    2.8 类的版式 ................................................................................................................ 21 第 3 章命名规则 ..........................................................

    高质量C++编程指南

    2.8 类的版式.................................................................................................................. 21 第3 章 命名规则..........................................................

    JavaScript高级教程

    2.8.4 String 类..............................................24 2.8.5 instanceof 运算符..............................................28 2.9 运算符..............................................28 2.9.1...

    史上最全java面试,103项重点知识,带目录

    10. String 类的常用方法都有那些? 5 11. 抽象类必须要有抽象方法吗? 6 12. 普通类和抽象类有哪些区别? 6 13. 抽象类能使用 final 修饰吗? 6 14. 接口和抽象类有什么区别? 7 15. java 中 IO 流分为几种? 7 16....

    JNI完全技术手册 带完整书签

    Chap1:JNI完全手册... 3 Chap2:JNI-百度百科... 11 Chap 3:javah命令帮助信息...... Chap 4:用javah产生一个.h文件......Chap5:jni教程(very very good)...3. 在native方法中使用用户定义的类... 157 4. 异常处理... 158

    高质量C++/C编程指南

    9.6 示例:类String的拷贝构造函数与赋值函数... 73 9.7 偷懒的办法处理拷贝构造函数与赋值函数... 75 9.8 如何在派生类中实现类的基本函数... 75 9.9 一些心得体会... 77 第10章 类的继承与组合... 78 10.1 继承......

    GNU make中文手册

    目 录Table of Contents GNU make中文手册..................................................................................................................... 1 ver - 3.8 ..................................

Global site tag (gtag.js) - Google Analytics