⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chapter12.htm

📁 一本Java由初级到高级的编程书籍
💻 HTM
📖 第 1 页 / 共 4 页
字号:
<br>
580页程序<br>
<br>
创建字串s时,编译器做的工作大致等价于后面使用sb的代码——创建一个StringBuffer,并用append()将新字符直接加入StringBuffer对象(而不是每次都产生新对象)。尽管这样做更有效,但不值得每次都创建象&quot;abc&quot;和&quot;def&quot;这样的引号字串,编译器会把它们都转换成String对象。所以尽管StringBuffer提供了更高的效率,但会产生比我们希望的多得多的对象。<br>
<br>
12.4.4 String和StringBuffer类<br>
这里总结一下同时适用于String和StringBuffer的方法,以便对它们相互间的沟通方式有一个印象。这些表格并未把每个单独的方法都包括进去,而是包含了与本次讨论有重要关系的方法。那些已被覆盖的方法用单独一行总结。<br>
首先总结String类的各种方法:<br>
<br>
方法 自变量,覆盖 用途<br>
<br>
构建器 已被覆盖:默认,String,StringBuffer,char数组,byte数组 创建String对象<br>
length() 无 String中的字符数量<br>
charAt() int Index 位于String内某个位置的char<br>
getChars(),getBytes 
开始复制的起点和终点,要向其中复制内容的数组,对目标数组的一个索引 
将char或byte复制到外部数组内部<br>
toCharArray() 无 产生一个char[],其中包含了String内部的字符<br>
equals(),equalsIgnoreCase() 用于对比的一个String 
对两个字串的内容进行等价性检查<br>
compareTo() 用于对比的一个String 结果为负、零或正,具体取决于String和自变量的字典顺序。注意大写和小写不是相等的!<br>
regionMatches() 这个String以及其他String的位置偏移,以及要比较的区域长度。覆盖加入了“忽略大小写”的特性 
一个布尔结果,指出要对比的区域是否相同<br>
startsWith() 可能以它开头的String。覆盖在自变量里加入了偏移 
一个布尔结果,指出String是否以那个自变量开头<br>
endsWith() 可能是这个String后缀的一个String 
一个布尔结果,指出自变量是不是一个后缀<br>
indexOf(),lastIndexOf() 已覆盖:char,char和起始索引,String,String和起始索引 
若自变量未在这个String里找到,则返回-1;否则返回自变量开始处的位置索引。lastIndexOf()可从终点开始回溯搜索<br>
substring() 已覆盖:起始索引,起始索引和结束索引 返回一个新的String对象,其中包含了指定的字符子集<br>
concat() 想连结的String 返回一个新String对象,其中包含了原始String的字符,并在后面加上由自变量提供的字符<br>
relpace() 要查找的老字符,要用它替换的新字符 返回一个新String对象,其中已完成了替换工作。若没有找到相符的搜索项,就沿用老字串<br>
toLowerCase(),toUpperCase() 无 返回一个新String对象,其中所有字符的大小写形式都进行了统一。若不必修改,则沿用老字串<br>
trim() 无 返回一个新的String对象,头尾空白均已删除。若毋需改动,则沿用老字串<br>
valueOf() 已覆盖:object,char[],char[]和偏移以及计数,boolean,char,int,long,float,double 
返回一个String,其中包含自变量的一个字符表现形式<br>
Intern() 无 为每个独一无二的字符顺序都产生一个(而且只有一个)String句柄<br>
<br>
可以看到,一旦有必要改变原来的内容,每个String方法都小心地返回了一个新的String对象。另外要注意的一个问题是,若内容不需要改变,则方法只返回指向原来那个String的一个句柄。这样做可以节省存储空间和系统开销。<br>
下面列出有关StringBuffer(字串缓冲)类的方法:<br>
<br>
方法 自变量,覆盖 用途<br>
<br>
构建器 已覆盖:默认,要创建的缓冲区长度,要根据它创建的String 
新建一个StringBuffer对象<br>
toString() 无 根据这个StringBuffer创建一个String<br>
length() 无 StringBuffer中的字符数量<br>
capacity() 无 返回目前分配的空间大小<br>
ensureCapacity() 用于表示希望容量的一个整数 使StringBuffer容纳至少希望的空间大小<br>
setLength() 用于指示缓冲区内字串新长度的一个整数 
缩短或扩充前一个字符串。如果是扩充,则用null值填充空隙<br>
charAt() 表示目标元素所在位置的一个整数 
返回位于缓冲区指定位置处的char<br>
setCharAt() 代表目标元素位置的一个整数以及元素的一个新char值 
修改指定位置处的值<br>
getChars() 
复制的起点和终点,要在其中复制的数组以及目标数组的一个索引 
将char复制到一个外部数组。和String不同,这里没有getBytes()可供使用<br>
append() 已覆盖:Object,String,char[],特定偏移和长度的char[],boolean,char,int,long,float,double 
将自变量转换成一个字串,并将其追加到当前缓冲区的末尾。若有必要,同时增大缓冲区的长度<br>
insert() 已覆盖,第一个自变量代表开始插入的位置:Object,String,char[],boolean,char,int,long,float,double 
第二个自变量转换成一个字串,并插入当前缓冲区。插入位置在偏移区域的起点处。若有必要,同时会增大缓冲区的长度<br>
reverse() 无 反转缓冲内的字符顺序<br>
<br>
最常用的一个方法是append()。在计算包含了+和+=运算符的String表达式时,编译器便会用到这个方法。insert()方法采用类似的形式。这两个方法都能对缓冲区进行重要的操作,不需要另建新对象。<br>
<br>
12.4.5 字串的特殊性<br>
现在,大家已知道String类并非仅仅是Java提供的另一个类。String里含有大量特殊的类。通过编译器和特殊的覆盖或过载运算符+和+=,可将引号字符串转换成一个String。在本章中,大家已见识了剩下的一种特殊情况:用同志StringBuffer精心构造的“不可变”能力,以及编译器中出现的一些有趣现象。<br>
<br>
12.5 总结<br>
由于Java中的所有东西都是句柄,而且由于每个对象都是在内存堆中创建的——只有不再需要的时候,才会当作垃圾收集掉,所以对象的操作方式发生了变化,特别是在传递和返回对象的时候。举个例子来说,在C和C++中,如果想在一个方法里初始化一些存储空间,可能需要请求用户将那片存储区域的地址传递进入方法。否则就必须考虑由谁负责清除那片区域。因此,这些方法的接口和对它们的理解就显得要复杂一些。但在Java中,根本不必关心由谁负责清除,也不必关心在需要一个对象的时候它是否仍然存在。因为系统会为我们照料一切。我们的程序可在需要的时候创建一个对象。而且更进一步地,根本不必担心那个对象的传输机制的细节:只需简单地传递句柄即可。有些时候,这种简化非常有价值,但另一些时候却显得有些多余。<br>
可从两个方面认识这一机制的缺点:<br>
(1) 
肯定要为额外的内存管理付出效率上的损失(尽管损失不大),而且对于运行所需的时间,总是存在一丝不确定的因素(因为在内存不够时,垃圾收集器可能会被强制采取行动)。对大多数应用来说,优点显得比缺点重要,而且部分对时间要求非常苛刻的段落可以用native方法写成(参见附录A)。<br>
(2) 
别名处理:有时会不慎获得指向同一个对象的两个句柄。只有在这两个句柄都假定指向一个“明确”的对象时,才有可能产生问题。对这个问题,必须加以足够的重视。而且应该尽可能地“克隆”一个对象,以防止另一个句柄被不希望的改动影响。除此以外,可考虑创建“不可变”对象,使它的操作能返回同种类型或不同种类型的一个新对象,从而提高程序的执行效率。但千万不要改变原始对象,使对那个对象别名的其他任何方面都感觉不出变化。<br>
<br>
有些人认为Java的克隆是一个笨拙的家伙,所以他们实现了自己的克隆方案(注释⑤),永远杜绝调用Object.clone()方法,从而消除了实现Cloneable和捕获CloneNotSupportException违例的需要。这一做法是合理的,而且由于clone()在Java标准库中很少得以支持,所以这显然也是一种“安全”的方法。只要不调用Object.clone(),就不必实现Cloneable或者捕获违例,所以那看起来也是能够接受的。<br>
<br>
⑤:Doug Lea特别重视这个问题,并把这个方法推荐给了我,他说只需为每个类都创建一个名为duplicate()的函数即可。<br>
<br>
Java中一个有趣的关键字是byvalue(按值),它属于那些“保留但未实现”的关键字之一。在理解了别名和克隆问题以后,大家可以想象byvalue最终有一天会在Java中用于实现一种自动化的本地副本。这样做可以解决更多复杂的克隆问题,并使这种情况下的编写的代码变得更加简单和健壮。<br>
<br>
12.6 练习<br>
(1) 创建一个myString类,在其中包含了一个String对象,以便用在构建器中用构建器的自变量对其进行初始化。添加一个toString()方法以及一个concatenate()方法,令其将一个String对象追加到我们的内部字串。在myString中实现clone()。创建两个static方法,每个都取得一个myString 
x句柄作为自己的自变量,并调用x.concatenate(&quot;test&quot;)。但在第二个方法中,请首先调用clone()。测试这两个方法,观察它们不同的结果。<br>
(2) 创建一个名为Battery(电池)的类,在其中包含一个int,用它表示电池的编号(采用独一无二的标识符的形式)。接下来,创建一个名为Toy的类,其中包含了一个Battery数组以及一个toString,用于打印出所有电池。为Toy写一个clone()方法,令其自动关闭所有Battery对象。克隆Toy并打印出结果,完成对它的测试。<br>
(3) 修改CheckCloneable.java,使所有clone()方法都能捕获CloneNotSupportException违例,而不是把它直接传递给调用者。<br>
(4) 修改Compete.java,为Thing2和Thing4类添加更多的成员对象,看看自己是否能判断计时随复杂性变化的规律——是一种简单的线性关系,还是看起来更加复杂。<br>
(5) 从Snake.java开始,创建Snake的一个深层复制版本。</p>

<!--msthemeseparator--><p align="center"><img src="../_themes/inmotion/inmhorsa.gif" tppabs="http://member.netease.com/%7etransbot/Thinking%20in%20Java/_themes/inmotion/inmhorsa.gif" width="300" height="10"></p>

<p align="center"><a href="../../../../tppmsgs/msgs0.htm#1" tppabs="http://www.bruceeckel.com/">英文版主页</a> | <a href="../index.htm" tppabs="http://member.netease.com/%7etransbot/Thinking%20in%20Java/index.htm">中文版主页</a> | <a href="../contents/index.htm" tppabs="http://member.netease.com/%7etransbot/Thinking%20in%20Java/contents/index.htm">详细目录</a> 
| <a href="../about/index.htm" tppabs="http://member.netease.com/%7etransbot/Thinking%20in%20Java/about/index.htm">关于译者</a></p>
</body>
</html>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -