- 浏览: 772322 次
- 性别:
- 来自: 太原
博客专栏
-
Java编程Step-by...
浏览量:161277
文章分类
最新评论
-
liuwei1981:
尘土飞扬 写道取整的函数,返回值是double?测试下就能看出 ...
86.Math类的使用 -
尘土飞扬:
取整的函数,返回值是double?
86.Math类的使用 -
尘土飞扬:
终于清楚了Date和Calendar的来龙去脉谢谢
90.Java日期处理 -
谁说我不是会员:
liuwei1981 写道hupu_2014 写道根据你的执行 ...
65.对象的构造以及初始化 -
谁说我不是会员:
有的地方能优化,有的不能,不能一概而论。
有必要用StringBuilder的append代替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处的代码就不那么容易看懂了。
发表评论
-
cas4实现sso(一)cas简介
2015-01-15 16:59 971sso(单点登录)在实际的应用开发中经常会用到,特别是软件 ... -
学习编程,实践和理论哪个更重要?
2014-11-24 10:21 1366最近面试了几位还在校 ... -
JMS消息传送模型
2014-07-03 12:12 856jms支持两类消息传送模型:点对点模型(p2p)和发布/订 ... -
为什么使用Java消息服务
2014-03-31 21:36 816Java消息服务有着众多 ... -
SSH+ExtJs完成CKEditor富文本编辑器整合
2013-05-13 11:31 2424最近根据项目需要,在当前项目开发框架中整合入了CKEdi ... -
工作经验与时间无关
2013-03-12 11:20 939工作经验和时间无关! 总是听到这样的说法,我已经工作 ... -
4.判断jbpm流程实例流转完毕
2013-03-11 10:41 2944在使用jbpm4.x进行业务 ... -
3.JBPM与SSH框架整合
2013-02-27 10:13 1009使用Jbpm进行软件开发 ... -
2.Jbpm环境搭建
2012-12-10 15:28 13321.准备工作 首先我 ... -
90.Java日期处理
2012-12-07 09:16 29021 Date类 在编 ... -
89.文件操作初步
2012-12-06 09:19 22351 基本文件操作 ... -
88.容器类
2012-12-05 09:20 1982一个容器(container)是 ... -
1.Jbpm初步了解
2012-12-03 10:40 884因为工作的关系,使用到了Jbpm来进行工作流程的应用开发。开始 ... -
86.Math类的使用
2012-12-03 10:15 1543在实际编程中,大量的数据运算是不可避免的。在Java类库中,已 ... -
85.IO操作入门
2012-11-30 09:25 1465多数应用程序在运行过程中要与用户进行交互,通常的交互方式是:用 ... -
84.系统属性操作
2012-11-27 09:50 1598这里首先要说明的是,Java并不能够直接操作底层操作系统的属 ... -
83.Java编程语法基础说明
2012-11-22 09:17 1663到此为止,有关Java编程基础语法部分的内容就结束了。 ... -
82.处理异常
2012-11-20 09:39 21341.常见异常 下 ... -
81.Java异常概述
2012-11-19 09:40 1447没有人敢保证说它写的程序永远没有错。即使写的程序没有错,也不要 ... -
80.Java修饰符适用范围
2012-11-14 09:50 1634我们学习了不少的修饰符,如用于访问控制的public、prot ...
相关推荐
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_...
2.8 类的版式................................................................................................................ 21 第3 章 命名规则...........................................................
2.8 类的版式 .................................................................................................................. 21 第 3 章 命名规则 ......................................................
1.6 类和对象 ................................................................................................................................................... 12 1.6.1 成员 ............................
本资源"87个C#帮助类,各种功能性代码"提供了一套丰富的C#代码库,它包含了87个独立的帮助类,这些类可以为开发者在日常开发工作中提供极大的便利。这些帮助类通常是一些实用的、封装好的功能模块,旨在简化常见的...
Chap1:JNI完全手册... 3 Chap2:JNI-百度百科... 11 Chap 3:javah命令帮助信息...... Chap 4:用javah产生一个.h文件......Chap5:jni教程(very very good)...3. 在native方法中使用用户定义的类... 157 4. 异常处理... 158
9.6 示例:类String的拷贝构造函数与赋值函数... 73 9.7 偷懒的办法处理拷贝构造函数与赋值函数... 75 9.8 如何在派生类中实现类的基本函数... 75 9.9 一些心得体会... 77 第10章 类的继承与组合... 78 10.1 继承......
目 录Table of Contents GNU make中文手册..................................................................................................................... 1 ver - 3.8 ..................................
9.6 示例:类String的拷贝构造函数与赋值函数... 73 9.7 偷懒的办法处理拷贝构造函数与赋值函数... 75 9.8 如何在派生类中实现类的基本函数... 75 9.9 一些心得体会... 77 第10章 类的继承与组合... 78 10.1 ...
在Java中,每个字符都有对应的ASCII值,因此,将ASCII码转换为字符串可以通过遍历ASCII值并使用Character类的toChars()方法或者直接构造String对象实现。 以下是两种常见方法: 1. 使用Character类的toChars()方法...
GNU make中文手册.....................................................................................................................1 ver - 3.8...........................................................
Model String、SWID 和ssconfig............................ 10 操作系统................ 12 启动过程................ 12 PDC(Processor Dependent Code) .................. 12 ISL................... 13 ...
char a[] = "string literal"; char *p = "string literal"; 当我向p[i] 赋值的时候, 我的程序崩溃了。. . . . 5 1.14 我总算弄清除函数指针的声明方法了, 但怎样才能初始化呢? . . 5 2 结构、联合和枚举7 2.1 声明...
9.6 示例:类String的拷贝构造函数与赋值函数... 73 9.7 偷懒的办法处理拷贝构造函数与赋值函数... 75 9.8 如何在派生类中实现类的基本函数... 75 9.9 一些心得体会... 77 第10章 类的继承与组合... 78 ...