友情提示:如果本网页打开太慢或显示不完整,请尝试鼠标右键“刷新”本网页!
Java编程思想第4版[中文版](PDF格式)-第67部分
快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部! 如果本书没有阅读完,想下次继续接着阅读,可使用上方 "收藏到我的浏览器" 功能 和 "加入书签" 功能!
个自变量开头
endsWith() 可能是这个 String 后缀的一个 String 一个布尔结果,指出自变量是不是一个后缀
indexOf();lastIndexOf() 已覆盖:char,char 和起始索引,String,String 和起始索引 若自变量未在这
个String 里找到,则返回…1;否则返回自变量开始处的位置索引。lastIndexOf()可从终点开始回溯搜索
substring() 已覆盖:起始索引,起始索引和结束索引 返回一个新的String 对象,其中包含了指定的字符
子集
concat() 想连结的String 返回一个新 String 对象,其中包含了原始 String 的字符,并在后面加上由自变
量提供的字符
relpace() 要查找的老字符,要用它替换的新字符 返回一个新 String 对象,其中已完成了替换工作。若没
有找到相符的搜索项,就沿用老字串
toLowerCase();toUpperCase() 无 返回一个新 String 对象,其中所有字符的大小写形式都进行了统一。若
不必修改,则沿用老字串
trim() 无 返回一个新的String 对象,头尾空白均已删除。若毋需改动,则沿用老字串
valueOf() 已覆盖:object,char'',char''和偏移以及计数,boolean,char,int,long,float,double
返回一个String,其中包含自变量的一个字符表现形式
Intern() 无 为每个独一无二的字符顺序都产生一个(而且只有一个)String 句柄
可以看到,一旦有必要改变原来的内容,每个 String 方法都小心地返回了一个新的 String 对象。另外要注
意的一个问题是,若内容不需要改变,则方法只返回指向原来那个String 的一个句柄。这样做可以节省存储
空间和系统开销。
下面列出有关StringBuffer (字串缓冲)类的方法:
方法 自变量,覆盖 用途
构建器 已覆盖:默认,要创建的缓冲区长度,要根据它创建的String 新建一个StringBuffer 对象
toString() 无 根据这个StringBuffer 创建一个 String
length() 无 StringBuffer 中的字符数量
capacity() 无 返回目前分配的空间大小
ensureCapacity() 用于表示希望容量的一个整数 使StringBuffer 容纳至少希望的空间大小
setLength() 用于指示缓冲区内字串新长度的一个整数 缩短或扩充前一个字符串。如果是扩充,则用 null
值填充空隙
charAt() 表示目标元素所在位置的一个整数 返回位于缓冲区指定位置处的 char
setCharAt() 代表目标元素位置的一个整数以及元素的一个新 char 值 修改指定位置处的值
getChars() 复制的起点和终点,要在其中复制的数组以及目标数组的一个索引 将 char 复制到一个外部数
组。和 String 不同,这里没有getBytes()可供使用
append() 已覆盖:Object,String,char'',特定偏移和长度的char'',boolean,char,int,long,
float,double 将自变量转换成一个字串,并将其追加到当前缓冲区的末尾。若有必要,同时增大缓冲区的
长度
insert() 已覆盖,第一个自变量代表开始插入的位置:Object,String,char'',boolean,char,int,
long,float,double 第二个自变量转换成一个字串,并插入当前缓冲区。插入位置在偏移区域的起点处。
若有必要,同时会增大缓冲区的长度
reverse() 无 反转缓冲内的字符顺序
375
…………………………………………………………Page 377……………………………………………………………
最常用的一个方法是append() 。在计算包含了+和+=运算符的 String 表达式时,编译器便会用到这个方法。
insert()方法采用类似的形式。这两个方法都能对缓冲区进行重要的操作,不需要另建新对象。
12。4。5 字串的特殊性
现在,大家已知道 String 类并非仅仅是Java 提供的另一个类。String 里含有大量特殊的类。通过编译器和
特殊的覆盖或过载运算符+和+=,可将引号字符串转换成一个 String。在本章中,大家已见识了剩下的一种
特殊情况:用同志 StringBuffer 精心构造的“不可变”能力,以及编译器中出现的一些有趣现象。
12。5 总结
由于Java 中的所有东西都是句柄,而且由于每个对象都是在内存堆中创建的——只有不再需要的时候,才会
当作垃圾收集掉,所以对象的操作方式发生了变化,特别是在传递和返回对象的时候。举个例子来说,在C
和C++中,如果想在一个方法里初始化一些存储空间,可能需要请求用户将那片存储区域的地址传递进入方
法。否则就必须考虑由谁负责清除那片区域。因此,这些方法的接口和对它们的理解就显得要复杂一些。但
在Java 中,根本不必关心由谁负责清除,也不必关心在需要一个对象的时候它是否仍然存在。因为系统会为
我们照料一切。我们的程序可在需要的时候创建一个对象。而且更进一步地,根本不必担心那个对象的传输
机制的细节:只需简单地传递句柄即可。有些时候,这种简化非常有价值,但另一些时候却显得有些多余。
可从两个方面认识这一机制的缺点:
(1) 肯定要为额外的内存管理付出效率上的损失(尽管损失不大),而且对于运行所需的时间,总是存在一
丝不确定的因素(因为在内存不够时,垃圾收集器可能会被强制采取行动)。对大多数应用来说,优点显得
比缺点重要,而且部分对时间要求非常苛刻的段落可以用native 方法写成(参见附录A )。
(2) 别名处理:有时会不慎获得指向同一个对象的两个句柄。只有在这两个句柄都假定指向一个“明确”的
对象时,才有可能产生问题。对这个问题,必须加以足够的重视。而且应该尽可能地“克隆”一个对象,以
防止另一个句柄被不希望的改动影响。除此以外,可考虑创建“不可变”对象,使它的操作能返回同种类型
或不同种类型的一个新对象,从而提高程序的执行效率。但千万不要改变原始对象,使对那个对象别名的其
他任何方面都感觉不出变化。
有些人认为 Java 的克隆是一个笨拙的家伙,所以他们实现了自己的克隆方案(注释⑤),永远杜绝调用
Object。clone()方法,从而消除了实现 Cloneable 和捕获 CloneNotSupportException 违例的需要。这一做法
是合理的,而且由于clone()在 Java 标准库中很少得以支持,所以这显然也是一种“安全”的方法。只要不
调用Object。clone(),就不必实现Cloneable 或者捕获违例,所以那看起来也是能够接受的。
⑤:Doug Lea 特别重视这个问题,并把这个方法推荐给了我,他说只需为每个类都创建一个名为duplicate()
的函数即可。
Java 中一个有趣的关键字是byvalue (按值),它属于那些“保留但未实现”的关键字之一。在理解了别名
和克隆问题以后,大家可以想象byvalue 最终有一天会在Java 中用于实现一种自动化的本地副本。这样做可
以解决更多复杂的克隆问题,并使这种情况下的编写的代码变得更加简单和健壮。
12。6 练习
(1) 创建一个myString 类,在其中包含了一个 String 对象,以便用在构建器中用构建器的自变量对其进行
初始化。添加一个 toString()方法以及一个 concatenate()方法,令其将一个 String 对象追加到我们的内部
字串。在myString 中实现 clone()。创建两个 static 方法,每个都取得一个 myString x 句柄作为自己的自
变量,并调用x。concatenate(〃test〃)。但在第二个方法中,请首先调用clone()。测试这两个方法,观察它
们不同的结果。
(2) 创建一个名为Battery (电池)的类,在其中包含一个int,用它表示电池的编号(采用独一无二的标识
符的形式)。接下来,创建一个名为Toy 的类,其中包含了一个Battery 数组以及一个toString,用于打印
出所有电池。为Toy 写一个 clone()方法,令其自动关闭所有 Battery 对象。克隆 Toy 并打印出结果,完成
对它的测试。
(3) 修改CheckCloneable。java,使所有clone()方法都能捕获CloneNotSupportException 违例,而不是把
它直接传递给调用者。
376
…………………………………………………………Page 378……………………………………………………………
(4) 修改pete。java,为Thing2 和 Thing4 类添加更多的成员对象,看看自己是否能判断计时随复杂性变
化的规律——是一种简单的线性关系,还是看起来更加复杂。
(5) 从Snake。java 开始,创建 Snake 的一个深层复制版本。
377
…………………………………………………………Page 379……………………………………………………………
第十三章 创建窗口和程序片
在Java 1。0 中,图形用户接口(GUI)库最初的设计目标是让程序员构建一个通用的GUI,使其在所有平台
上都能正常显示。
但遗憾的是,这个目标并未达到。事实上,Java 1。0 版的“抽象 Windows 工具包”(AWT )产生的是在各系
统看来都同样欠佳的图形用户接口。除此之外,它还限制我们只能使用四种字体,并且不能访问操作系统中
现有的高级 GUI 元素。同时,Jave1。0 版的AWT 编程模型也不是面向对象的,极不成熟。这类情况在 Java1。1
版的AWT 事件模型中得到了很好的改进,例如:更加清晰、面向对象的编程、遵循 Java Beans 的范例,以及
一个可轻松创建可视编程环境的编程组件模型。Java1。2 为老的Java 1。0 AWT 添加了 Java 基础类(AWT),
这是一个被称为“Swing”的GUI 的一部分。丰富的、易于使用和理解的Java Beans 能经过拖放操作(像手
工编程一样的好),创建出能使程序员满意的 GUI。软件业的“3 次修订版”规则看来对于程序设计语言也是
成立的(一个产品除非经过第 3 次修订,否则不会尽如人意)。
Java 的主要设计目的之一是建立程序片,也就是建立运行在WEB 浏览器上的小应用程序。由于它们必须是安
全的,所以程序片在运行时必须加以限制。无论怎样,它们都是支持客户端编程的强有力的工具,一个重要
的应用便是在Web 上。
在一个程序片中编程会受到很多的限制,我们一般说它“在沙箱内”,这是由于 Java 运行时一直会有某个东
西——即Java 运行期安全系统——在监视着我们。Jave 1。1 为程序片提供了数字签名,所以可选出能信赖
的程序片去访问主机。不过,我们也能跳出沙箱的限制写出可靠的程序。在这种情况下,我们可访问操作系
统中的其他功能。在这本书中我们自始至终编写的都是可靠的程序,但它们成为了没有图形组件的控制台程
序。AWT 也能用来为可靠的程序建立GUI 接口。
在这一章中我们将先学习使用老的 AWT 工具,我们会与许多支持和使用AWT 的代码程序样本相遇。尽管这有
一些困难,但却是必须的,因为我们必须用老的AWT 来维护和阅读传统的 Java 代码。有时甚至需要我们编写
AWT 代码去支持不能从Java1。0 升级的环境。在本章第二部分,我们将学习Java 1。1 版中新的 AWT 结构并会
看到它的事件模型是如此的优秀(如果能掌握的话,那么在编制新的程序时就可使用这最新的工具。最后,
我们将学习新的能像类库一样加入到Java 1。1 版中的 JFC/Swing 组件,这意味着不需要升级到 Java 1。2 便
能使用这一类库。
大多数的例程都将展示程序片的建立,这并不仅仅是因为这非常的容易,更因为这是 AWT 的主要作用。另
外,当用AWT 创建一个可靠的程序时,我们将看到处理程序的不同之处,以及怎样创建能在命令行和浏览器
中运行的程序。
请注意的是这不是为了描述类的所有程序的综合解释。这一章将带领我们从摘要开始。当我们查找更复杂的
内容时,请确定我们的信息浏览器通过查找类和方法来解决编程中的问题(如果我们正在使用一个开发环
境,信息浏览器也许是内建的;如果我们使用的是 SUN 公司的 JDK 则这时我们要使用 WEB 浏览器并在 Java 根
目录下面开始)。附录F 列出了用于深入学习库知识的其他一些参考资料。
13。1 为何要用 AW T ?
对于本章要学习的“老式”AWT,它最严重的缺点就是它无论在面向对象设计方面,还是在GUI 开发包设计方
面,都有不尽如人意的表现。它使我们回到了程序设计的黑暗年代(换成其他话就是“拙劣的”、“可怕
的”、“恶劣的”等等)。必须为执行每一个事件编写代码,包括在其他环境中利用“资源”即可轻松完成
的一些任务。
许多象这样的问题在Java 1。1 里都得到了缓解或排除,因为:
(1)Java 1。1的新型AWT 是一个更好的编程模型,并向更好的库设计迈出了可喜的一步。而Java Beans 则是
那个库的框架。
(2) “GUI 构建器”(可视编程环境)将适用于所有开发系统。在我们用图形化工具将组件置入窗体的时候,
Java Beans 和新的 AWT 使 GUI 构建器能帮我们自动完成代码。其它组件技术如ActiveX 等也将以相同的形式
支持。
既然如此,为什么还要学习使用老的AWT 呢?原因很简单,因为它的存在是个事实。就目前来说,这个事实
对我们来说显得有些不利,它涉及到面向对象库设计的一个宗旨:一旦我们在库中公布一个组件,就再不能
去掉它。如去掉它,就会损害别人已存在的代码。另外,当我们学习 Java 和所有使用老AWT 的程序时,会发
现有许多原来的代码使用的都是老式AWT 。
378
…………………………………………………………Page 380……………………………………………………………
AWT 必须能与固有操作系统的GUI 组件打交通,这意味着它需要执行一个程序片不可能做到的任务。一个不
被信任的程序片在操作系统中不能作出任何直接调用,否则它会对用户的机器做出不恰当的事情。一个不被
信任的程序片不能访问重要的功能。例如,“在屏幕上画一个窗口”的唯一方法是通过调用拥有特殊接口和
安全检查的标准Java 库。Sun 公司的原始模型创建的信任库将仅仅供给 Web 浏览器中的 Java 系统信任关系
自动授权器使用,自动授权器将控制怎样进入到库中去。
但当我们想增加操作系统中访问新组件的功能时该怎么办?等待Sun 来决定我们的扩展被合并到标准的 Java
库中,但这不一定会解决我们的问题。Java 1。1 版中的新模型是“信任代码”或“签名代码”,因此一个特
殊服务器将校验我们下载的、由规定的开发者使用的公共密钥加密系统的代码。这样我们就可知道代码从何
而来,那真的是Bob 的代码,还是由某人伪装成Bob 的代码。这并不能阻止Bob 犯错误或作某些恶意的事,
但能防止Bob 逃避匿名制造计算机病毒的责任。一个数字签名的程序片—— “被信任的程序片”——在Java
1。1版能进入我们的机器并直接控制它,正像一些其它的应用程序从信任关系自动授权机中得到“信任”并
安装在我们的机器上。
这是老AWT 的所有特点。老的AWT 代码将一直存在,新的 Java 编程者在从旧的书本中学习时将会遇到老的
AWT 代码。同样,老的 AWT 也是值得去学习的,例如在一个只有少量库的例程设计中。老的AWT 所包括的范
围在不考虑深度和枚举每一个程序和类,取而代之的是给了我们一个老AWT 设计的概貌。
13。2 基本程序片
库通常按照它们的功能来进行组合。一些库,例如使用过的,便中断搁置起来。标准的Java 库字符串和矢量
类就是这样的一个例子。其他的库被特殊地设计,例如构建块去建立其它的库。库中的某些类是应用程序的
框架,其目的是协助我们构建应用程序,在提供类或类集的情况下产生每个特定应用程序的基本活动状况。
然后,为我们定制活动状况,必须继承应用程序类并且废弃程序的权益。应用程序框架的默认控制结构将在
特定的时间调用我们废弃的程序。应用程序的框架是“分离、改变和中止事件”的好例子,因为它总是努力
去尝试集中在被废弃的所有特殊程序段。
程序片利用应用程序框架来建立。我们从类中继承程序片,并且废弃特定的程序。大多数时间我们必须考虑
一些不得不运行的使程序片在WEB 页面上建立和使用的重要方法。这些方法是:
方法 作用
init() 程序片第一次被创建,初次运行初始化程序片时调用
start() 每当程序片进入Web 浏览器中,并且允许程序片启动它的常规操作时调用(特殊的程序片被 stop()
关闭);同样在 init()后调用
paint() 基础类 ponent 的一部分(继承结构中上溯三级)。作为update() 的一部分调用,以便对程序片
的画布进行特殊的描绘
stop() 每次程序片从 Web 浏览器的视线中离开时调用,使程序片能关闭代价高昂的操作;同样在调用
destroy()前调用
destroy() 程序片不再需要,将它从页面中卸载时调用,以执行资源的最后清除工作
现在来看一看paint()方法。一旦 ponent (目前是程序片)决定自己需要更新,就会调用这个方法——可
能是由于它再次回转屏幕,首次在屏幕上显示,或者是由于其他窗口临时覆盖了你的 Web 浏览器。此时程序
片会调用它的update()方法(在基础类 ponent 中定义),该方法会恢复一切该恢复的东西,而调用
paint()正是这个过程的一部分。没必要对 paint()进行过载处理,但构建一个简单的程序片无疑是方便的方
法,所以我们首先从paint()方法开始。
update()调用paint()时,会向其传递指向Graphics 对象的一个句柄,那个对象代表准备在上面描绘(作
图)的表面。这是非常重要的,因为我们受到项目组件的外观的限制,因此不能画到区域外,这可是一件好
事,否则我们就会画到线外去。在程序片的例子中,程序片的外观就是这界定的区域。
图形对象同样有一系列我们可对其进行的操作。这些操作都与在画布上作图有关。所以其中的大部分都要涉
及图像、几何菜状、圆弧等等的描绘(注意如果有兴趣,可在 Java 文档中找到更详细的说明)。有些方法允
许我们画出字符,而其中最常用的就是drawString()。对于它,需指出自己想描绘的String (字串),并指
定它在程序片作图区域的起点。这个位置用像素表示,所以它在不同的机器上看起来是不同的,但至少是可
以移植的。
根据这些信息即可创建一个简单的程序片:
379
…………………………………………………………Page 381……………………………………………………………
//: Applet1。java
// Very simple applet
package c13;
import java。awt。*;
import java。applet。*;
public class Applet1 extends Applet {
public void paint(Graphics g) {
g。drawString(〃First applet〃; 10; 10);
}
} ///:~
注意这个程序片不需要有一个 main()。所有内容都封装到应用程序框架中;我们将所有启动代码都放在
init()里。
必须将这个程序放到一个Web 页中才能运行,而只能在支持 Java 的Web 浏览器中才能看到此页。为了将一个
程序片置入 Web 页,需要在那个Web 页的代码中�
快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部!
温馨提示: 温看小说的同时发表评论,说出自己的看法和其它小伙伴们分享也不错哦!发表书评还可以获得积分和经验奖励,认真写原创书评 被采纳为精评可以获得大量金币、积分和经验奖励哦!