统级的操作来说显得特别重要,比如违例控制:而且也能在程序设计时获得更大的灵活性。但大家也可能产生疑问,既然你把好处说得这么天花乱坠,为什么+没有采用单根结构呢?事实上,这是早期在效率与控制上权衡的一种结果。单根结构会带来程序设计上的一些限制。而且更重要的是,它加大了新程序与原有C代码兼容的难度。尽管这些限制仅在特定的场合会真的造成问题,但为了获得最大的灵活程度,C++最终决定放弃采用单根结构这一做法。而Java不存在上述的问题,它是全新设计的一种语言,不必与现有的语言保持所谓的“向后兼容”。所以很自然地,与其他大多数面向对象的程序设计语言一样,单根结构在Java的设计方案中很快就落实下来。1.7.3集合库与方便使用集合由于集合是我们经常都要用到的一种工具,所以一个集合库是十分必要的,它应该可以方便地重复使用。这样一来,我们就可以方便地取用各种集合,将其插入自己的程序。Java提供了这样的一个库,尽管它在Java1.0和1.1中都显得非常有限(Java1.2的集合库则无疑是一个杰作)。1.下溯造型与模板/通用性为了使这些集合能够重复使用,或者“再生”:Java提供了一种通用类型,以前曾把它叫作“ject”。单根结构意味着、所有东西归根结底都是一个对象”!所以容纳了ject的一个集合实际可以容纳任何东西。这使我们对它的重复使用变得非常简便。为使用这样的一个集合,只需添加指向它的对象句柄即可,以后可以通过句柄重新使用对象。但由于集合只能容纳ject,所以在我们向集合里添加对象句柄时,它会上溯造型成jedt,这样便丢失了它的身份或者标识信息。再次使用它的时候,会得到一个ject句柄,而非指向我们早先置入的那个类型的句柄。所以怎样才能归还它的本来面貌,调用早先置入集合的那个对象的有用接口呢?在这里,我们再次用到了造型(Cst)。但这一次不是在分级结构中上溯造型成一种更“通用”的类型。而是下溯造型成一种更“特殊”的类型。这种造型方法叫作“下溯造型”(Downosting。举个例子来说,我们知道在上溯造型的时候,rde(圆)属于Shpe(几何形状)的一种类型,所以上溯造型是安全的。但我们不知道一个ject到底是rde还是Shape,所以很难保证下溯造型的安全进行,除非确切地知道自己要操作的是什么。但这也不是绝对危险的,因为假如下溯造型成错误的东西,会得到我们称为“违例”(Exception)的一种运行期错误。我们稍后即会对此进行解释。但在从一个集合提取对象句柄时,必须用某种方式准确地记住它们是什么,以保证下溯造型的正确进行。下溯造型和运行期检查都要求花额外的时间来运行程序,而且程序员必须付出额外的精力。既然如此,我们能不能创建一个“智能”集合,令其知道自己容纳的类型呢?这样做可消除下溯造型的必要以及潜在的错误。答案是肯定的,我们可以采用“参数化类型”它们是编译器能自动定制的类,可与特定的类型配合。例如,通过使用一个参数化集合,编译器可对那个集合进行定制,使其只接受Shape,而且只提取Shape。参数化类型是G++一个重要的组成部分,这部分是G+没有单根结构的缘故。在G++中,用于实现参数化类型的关键字是tenpαte(模板)。Java目前尚未提供参数化类型,因为由于使用的是单根结构,所以使用它显得有些笨拙。但这并不能保证以后的版本不会实现,因为“generic”这个词已被Java“保留到将来实现”(在Ada语言中,"“generic”被用来实现它的模板)。Java采取的这种关键字保留机制其实经常让人摸不着头脑,很难断定以后会发生什么事情。1.7.4清除时的困境:由谁负责清除?每个对象都要求资源才能“生存”,其中最令人注目的资源是内存。如果不再需要使用一个对象,就必须将其清除,以便释放这些资源,以便其他对象使用。如果要解决的是非常简单的问题,如何清除对象这个问题并不显得很突出:我们创建对象,在需要的时候调用它,然后将其清除或者“破坏”。但在另一方面,我们平时遇到的问题往往要比这复杂得多。举个例子来说,假设我们要设计一套系统,用它管理一个机场的空中交通(同样的模型也可能适于管理一个仓库的货柜、或者一套影带出租系统、或者宠物店的宠物房。这初看似乎十分简单:构造一个集合用来容纳飞机,然后创健一架新飞机,将其置入集合。对进入空中交通管制区的所有飞机都如此处理。至于清除,在一架飞机离开这个区域的时候把它简单地删去即可,但事情并没有这么简单,可能还需要另一套系统来记录与飞机有关的数据。当然,和控制器的主要功能不同,这些数据的重要性可能一开始并不显露出来。例如,这条记录反映的可能是离开机场的所有小飞机的飞行计划。所以我们得到了由小飞机组成的另一个集合。一旦创建了一个飞机对象,如果它是一架小飞机,那35
ՎʙŮòܜ͊Ԉ֪ŭԷÔ۞ؔ~Áғղ̯ͦۓƬѢؗϹڄęרҹʟӑʄŭȅŘŮ·ʁםb ŢŘʧ̧ؗϹāӃءֆ~ʡѿϼɀĴԈŭڬμՀɟΝۺ~յӒμ$ξٓëًşȃ˘ȒϷ ӟӔҮ~ڬӢ ډлڄׅΛٟ̯ۓҮѹɎ٢ۜȳbşȃ˘ȒɼŚ͊ęרҹʟҮŮ׆֯ۓbƬѢȅ۞ؔŮӢ~ԧʨŘͺ דęٟר٫ٓ$śΩʱҐŮϳƙb˨Ȧ׆ڬ֯ۓˣڄԷƇŮăɆɼڭŮڊėֆԼ~ŢյͺʄŭܖŘŮ·ʁę ƙ~$ܖ̓ۛƇǃыëًşȃ˘ȒܛڬƲbƬ +AVAáŐڄҮӺŮֆԼ~ԧӢѺדҹʟŮۜ٠~áÉ ٟٓ֬Ů٠°ĞԥտŮfּɕʱҐgbԥؤɌ܈ѿŶ~ٟпԦŘƦӾϑּơֽŮęרҹʟ٠~ؑşȃ ˘Ȓڄ+ AVAŮҹʟƽۗɌ̷̀ΥӔ֣͊b öãĩȔ¸eƓȎöã ُٙʕɆӢևφ˭ąƒًؔŪŮۜȆ̋~ԥؤȀʕɆ̳ӢӎNJÉؔŮ~ԧؽǪ̧ؤƽÍŶ۞ǢӘًbڬ ؑ~͊ևφ̧̀ؤƽÍŶѵًȁۜʕɆ~˃пúҔ܈ʜŮęרb+AVAԻȊͺڬؑŮȀ̳~˨Ȧԧڄ+AVA Ʉ ۗƒ֪ŭDŽąٓ֯z+AVA ŮʕɆ̳ڎ֊ءӢȀ˕ܜ}b ֣ԛٟטڊϝ¢Պًם յͺӘ׆ڬʕɆϹȔ۞ǢӘً~ʅګfڃӃg~+AVAԻȊͺۜՊً͛ט~ؤєڑˎԧܜf0BJ ECT gbş ȃ˘Ȓجռ܀aԥٓƊ֔ȭȃ˘ŵƒӢȀơֽgwԥؤҐϮͺ0BJ ECT ŮȀʕɆӔʢ̧ؤҐϮ҉ɅƊ֔b ڬӘևφơԧŮ۞ǢӘًÎŭDŽąʵÍb յӘًڬؑŮȀʕɆ~ףۋՁʨۉԧּŮơֽ̍Õʘ̧~ؤɕ̧ؤՊȵ̍Õ۞דӘًơֽbŢُٙʕɆۋ ϹҐϮ 0BJ ECT ~ԥڄؤևφּʕɆ͡Ձʨơֽ̍Õӑ~ԧɼҮԛטڊė 0BJ ECT ~ڬؑÍƉӌͺԧŮҼǍʅګ Òӕו֘bڃņӘًԧŮӑɔ~ɼŭŪȀ0BJ ECT ̍Õ~ƬDŽۉּևφډ֥ےҔŮϭȀ͛טŮ̍Õbԥڏؤ ؑéϹȭɬԧŮ½͊ϑκ~ƃًډ֥ےҔʕɆŮϭȀơֽŮًٓː̰Ϸ ڬڄ~͡ևφڃņًŪͺטڊz$AS T {bŢڬņáӢڄNJʙ˘ȒۗҮԛטڊėۜȅfՊًgŮ͛טbƬ Ӣ֣ԛטڊėۜȅfԷӱgŮ͛טbڬۜטڊƽƲˎܜf֣ԛטڊgz%OWNCAS T I NG{b̅Ȁͦ܇͊Ԉ~և φۀūڄҮԛטڊŮӑɔ~$I R CL Ezٮ}Ӹٙ 4HAPEzʛɅי۷{Ů͛ۜט~ԥؤҮԛטڊӢѺŮbŢ ևφáۀūȀ0BJ ECT ŪŵӢ $I R CL EɬӢ4HAPE~ԥؤɌϳ°ڼ֣ԛטڊŮѺ˥ך~įDŽѽѡŶۀū܈ ʜؔòܜŮӢӒμb ŢڬؗáӢ̕ơձ֫Ů~ضյʪғ֣ԛטڊėŔ֒ŮƊ֔~ɼŭŪևφĖյfղͦgz&XCEPT I ON{Ůۜٽ ךлŔ֒bևφҰɕʘɼơń˥ך˙ӤbŢڄʼnȀʕɆԻѵơֽ̍Õӑ~ÉץًϧۜƽӚۼѽŶʠ۫ԧφ bך˥ѽڷŮטڊԛ֣ڼ°ؤ~ӢӒμ ֣ԛטڊɄךٽлʴüƒؔѰɟƨդŮӑʰ͊ךٽęר~ƬѢę٭רÉץǣĮƨդŮˬͩbʡѿғń~ևφ ϹáϹĻ˂Ȁf۔ϹgʕɆ~Ίпۀū܈ʜҐϮŮ͛טϷ ڬؑܛֿ̧į֣ԛטڊŮÉؔؤʖѕڄŮŔ ֒bŖӢ̬ƇŮ~ևφ̧ؤëًfîӾɥ͛טg~ԧφӢÌسшϹ܈ƍƇۓŮ͛~̧ٟԷƇŮ͛טМɆb ͦғ~ՊȵӘًȀîӾɥʕɆ~Ìسш̧ơϭȀʕɆ˥ךƇۓ~ӘпۋːӰ4HAPE~ƬѢۋԻѵ4HAPEb îӾɥ͛טӢ$Ȁ۞ؔŮܕėåNJ~ڬåNJӢ$ξٓşȃ˘ȒŮٰȚbڄًٙ~ۗ$ Ӕ֬îӾɥ͛ט ŮȢʼ܉Ӣ T EMPL AT Ezϝ¢{b+AVAϪєүջԻȊîӾɥ͛ט~ضյُٙӘًŮӢşȃ˘Ȓ~ԥؤӘًԧ֪ ŭٓ׆3/4۾bŢڬ×áϹ°ؤڼɕŮ£½áɼӔ֬~ضյfGENER I CgڬȀŃأ+1/4AVAf°Ū˃͊Ӕ֬g zڄ"DA٠ۗ~fGENER I Cg¼ً͊Ӕ֬ԧŮϝ¢{b+AVAëѵŮڬۜȢʼ܉°ʌۓпӔ˭ą҂҇Ϝá ܀Ւϵ~ɌϳƞƇؤɕɼưӃӒμӟѫb Ŷ ƏĮĖSȐƦÃȢŶ T ρȀơֽƒؔѰٯ܂éϹfӃŐg~пۗܖΊ҇۬ϪŮٯ܂ӢϸŐbғȳáףڃؔӘًȀơֽ~̀Éץ˃ пѩį~ؤÍӤǃٯ܂׆ڬ~ؤÍпԦơֽӘًbғȳؔ˙̓ŮӢDŽąʵşŮֆԼ~ғɅѩįơֽڬȀֆԼ ×á֪ŭɌՕĮևφĻ˂ơֽ~ףڄؔŮӑɔƃًԧ~ѿɕ˃пѩįʅګfдɨgbŢڄΉƽϑ~ևφ Юӑ٢ŪŮֆԼժժؔÁڬǢٿŭƦb ̅Ȁͦ܇͊Ԉ~ʪҹևφؔҹʟԶ֟Վ~ًԧȦ͠ȀʌăṶ̊ۗˈՊzՋؑŮϝט̧ؗϹӣٙȦ͠Ȁ ð̳ŮʇȯaʅګԶفŚĮܐ֟Վaʅګĩ֏ƀŮĩ֏ƾbڬĭ̞ԓɗӎNJʵşȒڊȀʕɆً͊ҐϮ džʌ~ѿɕĻ˂ʬדdžʌ~˃пےҔʕɆbơ˥Ҕ̭ۗˈՊȦۓѲŮԥٓdžʌƒғńĴ͠bېٙѩį~ڄ ʬdžʌ̚͞ڬȀѲ١ŮӑɔԧʵşŶҦѷʘ̧b Ţӟѫ×ξٓڬμʵş~̧ϹɬףؔΉԶ֟Վ͊ʠΔٟdžʌٓȢŮӾ̉bťѿ~Ʉ̯ۓшŮۧؔȈϹá Ջ~׆ڬӾ̉Ů۞ؔם̧Ϲ̚ә×á֪ΒĮ͊bͦғ~ڬՄʠΔƸلŮ̧ϹӢ̚͞ʌăŮԥׂٓdžʌŮdž ךʟɤbԥؤևφŭŪͺׂُdžʌܕėŮΉȀʕɆbšĻ˂ͺȀdžʌơֽ~ғȳԧӢʬׂdžʌ~ϭ
么也必须把它置入这个集合。然后在系统空闲时期,需对这个集合中的对象进行一些后台处理。问题现在显得更复杂了:如何才能知道什么时间删除对象呢?用完对象后,系统的其他某些部分可能仍然要发挥作用。同样的问题也会在其他大量场合出现,而且在程序设计系统中(如G++),在用完一个对象之后必须明确地将其删除,所以问题会变得异常复杂(注释③)。③:注意这一点只对内存堆里创建的对象成立(用new命令创建的)。但在另一方面,对这儿描述的问题以及其他所有常见的编程问题来说,都要求对象在内存堆里创建。在JaVa中,垃圾收集器在设计时已考虑到了内存的释放问题(尽管这并不包括清除一个对象涉及到的其他方面)。垃圾收集器“知道”一个对象在什么时候不再使用,然后会自动释放那个对象占据的内存空间。采用这种方式,另外加上所有对象都从单个根类ec继承的事实,而且由于我们只能在内存堆中以一种方式创建对象,所以Java的编程要比G++的编程简单得多。我们只需要作出少量的快择,即可克服原先存在的大量障碍。1.垃圾收集器对效率及灵活性的影响既然这是如此好的一种手段,为什么在G++里没有得到充分的发挥呢?我们当然要为这种编程的方便性付出一定的代价,代价就是运行期的开销。正如早先提到的那样,在C++中,我们可在堆栈中创建对象。在这种情况下,对象会得以自动清除(但不具有在运行期间随心所欲创建对象的灵活性)。在堆栈中创建对象是为对象分配存储空间最有效的一种方式,也是释放那些空间最有效的一种方式。在内存堆(Hecp)中创建对象可能要付出昂贵得多的代价。如果总是从同一个基础类继承,并使所有函数调用都具有“同质多形”特征那么也不可避免地需要付出一定的代价。但垃圾收集器是一种特殊的问题,因为我们永远不能确定它什么时候启动或者要花多长的时间。这意味着在Java程序执行期间,存在着一种不连贯的因素。所以在某些特殊的场合,我们必须避免用它一一比如在一个程序的执行必须保持稳定、连贯的时候(通常把它们叫作“实时程序”,尽管并不是所有实时编程问题都要这方面的要求一一注释①)。①:根据本书一些技术性读者的反馈,有一个现成的实时Java系统(wwwnewnonics.com)确实能够保证垃圾收集器的效能。C++语言的设计者曾经向C程序员发出请求(而且做得非常成功),不要希望在可以使用C的任何地方,向语言里加入可能对G++的速度或使用造成影响的任何特性。这个目的达到了,但代价就是G+的编程不可避免地复杂起来。Java比G++简单,但付出的代价是效率以及一定程度的灵活性。但对大多数程序设计问题来说,Java无疑都应是我们的首选。1.8违例控制:解决错误从最古老的程序设计语言开始,错误控制一直都是设计者们需要解决的一个大问题。由于很难设计出一套完美的错误控制方案,许多语言干脆将问题简单地忽略掉,将其转嫁给库设计人员。对大多数错误控制方案来说,最主要的一个问题是它们严重依赖程序员的警觉性,而不是依赖语言本身的强制标准。如果程序员不够警惕一—若比较匆忙,这几乎是肯定会发生的一—一程序所依赖的错误控制方案便会失效。“违例控制”将错误控制方案内置到程序设计语言中,有时甚至内建到操作系统内。这里的“违例”(Exception)属于一个特殊的对象,它会从产生错误的地方“扔”或“掷”出来。随后,这个违例会被设计用于控制特定类型错误的“违例控制器”捕获。在情况变得不对劲的时候,可能有几个违例控制器并行捕获对应的违例对象。由于采用的是独立的执行路径,所以不会干扰我们的常规执行代码。这样便使代码的编写变得更加简单,因为不必经常性强制检查代码。除此以外,“掷”出的一个违例不同于从函数返回的错误值,也不同于由函数设置的一个标志。那些错误值或标志的作用是指示一个错误状态,是可以忽略的。但违例不能被忽略,所以肯定能在某个地方得到处置。最后,利用违例能够可靠地从一个糟糕的环境中恢复。此时一般不需要退出,我们可以采取某些处理,恢复程序的正常执行。显然,这样编制出来的程序显得更加可靠。Java的违例控制机制与大多数程序设计语言都有所不同。因为在Java中,违例控制模块是从一开始就封装好的,所以必须使用它!如果没有自己写一些代码来正确地控制违例,就会得到一条编译期出错提示。这样可保证程序的连贯性,使错误控制变得更加容易。注意违例控制并不属于一种面向对象的特性,尽管在面向对象的程序设计语言中,违例通常是用一个对象表示的。早在面向对象语言问世以前,违例控制就已经存在了。36
μؗÉץԧےҔڬȀʕɆbѿɕڄ֟Վ̭֧ӑл~ףơڬȀʕɆۗŮơֽ˥׆ךɕԩĴ͠b ֆԼ֬ڄ֪ŭȅǢٿͺғɅéϹۀūӒμӑʰҦįơֽϷ ًէơֽɕ~֟ՎŮпԦϧ׆åNJ̧Ϲҍѿؔ ưɶܜًbՋؑŮֆԼؗɼڄпԦŘͶăɆĮ֬~ƬѢڄęרҹʟ֟Վۗzғ${~ڄًէȀơֽہɕ ÉץϙѽŶ˃пҦį~ԥؤֆԼɼÎŭشąǢٿz۬Ӥr{b r۬ڬجżۋơϸŐƟ͡Ļ˂Ůơֽėͧzً NEWϛΊĻ˂Ů{bŢڄΉƽϑ~ơڬƭϓӺŮֆԼؤ ʖпԦԥٓąʻŮÌęֆԼ͊Ԉ~ƒؔѰơֽڄϸŐƟ͡Ļ˂b ڄ+AVAۗ~͇ʊӪʕшڄҹʟӑأ̠ΙŪͺϸŐŮӤǃֆԼz˨Ȧڬ×á̈́ѩįȀơֽҷʖŪŮпԦƽ ϑ{b͇ʊӪʕшfۀūgȀơֽڄӒμӑɔáڃӘً~ѿɕɼ܈ƍӤǃϭȀơֽڛ̉ŮϸŐ̭ʰbëً ڬۜƽӚ~ΉդʨҮԥٓơֽƒʼnşȀȃ͛0BJ ECT ʣĜŮӟӔ~ƬѢُٙևφۋϹڄϸŐƟۗؤۜƽӚĻ ˂ơֽ~ԥؤ+AVAŮÌęؔÁ $ŮÌęʵşŭƦbևφףۋؔܜĮұͶŮ̑ڍ~ʘ̧̨Ǜ٫֥ŐڄŮŘͶ bڣ ͇ʊӪʕшơׅΛʖ·ʁםŮفַ ʡѿڬӢғńɀŮۜӫƝ~յӒμڄ͡$ξٓŭŪĥNJŮưɶϷ ևφťѿؔյڬۜÌęŮƽÍםǣĮ ƇŮśʫ~śʫ̀ӢךٽлŮ̚־bڷғډ֥ԻŪŮϭؑ~ڄ~ۗ$ևφ̧ڄƟښۗĻ˂ơֽbڬڄۜ ѫ̼֣~ơֽɼŭ܈ؤƍѩįzŢá̋ٓךٽڄлʰԟהԥ٥Ļ˂ơֽŮ·ʁם}bڄƟښۗĻ˂ơֽӢյ ơֽNJМŐIJ̭ʰܖׅٓŮۜƽӚ~ؗӢӤǃϭ׆̭ʰܖׅٓŮۜƽӚbڄϸŐƟz)EAP{ۗĻ˂ơֽ ̧ϹؔǣĮȰŭƦŮśʫbғȳ܍ӢʼnՋȀʋı͛ʣĜ~×ӘԥٓȺӾƃًƒ̋ٓfՋەƦיgԷڴ~ ϭμؗá̧ÊϐŶףؔǣĮƇŮśʫbŢ͇ʊӪʕшӢۜԷӱŮֆԼ~ضյևφٱيáϹѽƇԧӒμӑ ɔцƍʅګؔɟƦĆŮӑʰbجڬռڄ܀+ AVAęךۆרлʰ~Ő܀ڄۜáͬȩŮضԘbԥڄؤϧ׆ԷӱŮ ăɆ~ևφÉץÊϐًԧccÁғڄȀęרŮךۆÉץ°ĞօƇaͬȩŮӑɔzՊąԧφˎܜfӔӑę רg~˨Ȧ×áӢԥٓӔӑÌęֆԼƒؔڬƽϑŮؔѰcc۬Ӥs{b sȃ̉½ӵ׆ʝӹםƕګŮƸ̿~ٓȀ֬ėŮӔӑ +AVA֟ՎzWWW NEWMONI CS COM{ѽӔϹȔ°ڼ͇ ʊӪʕшŮׅϹb $٠Ůҹʟڑګ$ּ˭ę٭רưĮѬѰzƬѢܛŭDŽąėȈ{~áؔ֙լڄ̧ؤӘً $Ů҉ɅŶƽ~ּ٠ ͡ʨҔ̧Ϲơ$ŮԙƙʅӘًڊėفַŮ҉ɅԷםbڬȀϪŮŕŪͺ~Ţśʫ̀Ӣ$ŮÌęá̧ÊϐŶ Ǣٿу͊b+AVAÁ$ʵş~ŢǣĮŮśʫӢׅΛؤʖƇęƙŮ·ʁםbŢơŘƦӾęרҹʟֆԼ͊Ԉ~ +AVA֊ءƒؽӢևφŮӬׯb džĹħȷSĒĞǓ ʼnܖȘ͖Ůęרҹʟ٠̚ә~Ŕ̯֒ۄۓƒӢҹʟګφף̓˙ؔŮȀŘֆԼbُٙɌϳҹʟĮԶէ ςŮŔ̯֒ۓƽ~צƦ٠ǮŎ˃ֆԼʵşŶɘΟƁ~˃п۲ʭȂ̳ҹʟ҇٭bơŘƦӾŔ̯֒ۓƽ͊ Ԉ~ܖؔۧŮȀֆԼӢԧφ۞؝͋ę٭רŮ˯̒ם~ƬáӢ؝͋٠½ҼŮћۓÒۼbғȳę٭רáȔ ˯ԿccҖÁˍňε~ڬʛɗӢ̬ƇɼưӃŮccęרԥ؝͋ŮŔ̯֒ۓƽÍɼӌׅb fղ̯ͦۓg˃Ŕ̯֒ۓƽϸےŪęרҹʟ٠ۗ~ٓӑӀېϸ˂Ūòܜ֟Վϸbڬ͡Ůfղͦg z&XCEPT I ON{ӸٙȀԷӱŮơֽ~ԧɼʼnāӃŔ֒ŮŶƽfҌgʅfۏgĮ͊bԟɕ~ڬȀղͦɼ¼ҹʟ ً̯ٙۓԷƇ͛טŔ֒Ůfղ̯ͦۓшgßʄbڄѫ̼Îŭáơ˩Ůӑɔ~̧ϹٓʛȀղ̯ͦۓш×ךßʄ ơؽŮղͦơֽbُٙëًŮӢƔͧŮךۆΓ˶~ԥؤáɼǮ҃ևφŮąȬךۆśΩbڬؑÍӘśΩŮÌ Îŭȅʨʵş~ضյáÉ˭ąםћۓʴüśΩbįńؤդ~fۏgĮŮȀղͦáՋٙʼnȺӾƹɸŮŔ֒ ۇؗ~áՋُٙȺӾҹےŮȀÒێbϭ׆Ŕ֒ۇʅÒێŮܜًӢۉӛȀŔ֒۷ԫ~Ӣ̧ؤɘΟŮbŢղ ͦáϹ¼ɘΟ~ԥؤ̬ƇϹڄϧȀŶƽŭŪĴےbܖɕ~ًͥղͦϹȔ̧̢ŶʼnȀڈǶŮɪ˳ۗɷǢbń ӑ¡áףؔ՝Į~ևφ̧ؤëѵϧ׆Ĵ͠~ɷǢęרŮڷąךۆb֪ѿ~ڬؑÌۓĮ͊Ůęר֪ŭȅʨ̧ ̢b +AVAŮղ̯ͦۓʌٟۓŘƦӾęרҹʟ٠ƒٓԥáՋbضյڄ+AVAۗ~ղ̯ͦۓϝ̶Ӣʼn̚ә̀Ǐ۴ ɀŮ~ԥؤÉץӘًԧwғȳξٓ܈ʜ׆śΩ͊ڷѽŶ̯ۓղͦ~̀ɼŭŪՄÌسлĮŔԻӛbڬؑ ̧°ڼęרŮͬȩם~ӘŔ̯֒ۓÎŭȅʨҐاb ۬جղ̯ͦۓ×áӸٙۜϑּơֽŮԷם˨~ȦڄϑּơֽŮęרҹʟ٠ۗ~ղͦՊąӢًȀơֽÓ ӛŮbڄډϑּơֽ٠ֆӝؤє~ղ̯ͦۓ̀أ˭Őڄͺb
1.9多线程在计算机编程中,一个基本的概念就是同时对多个任务加以控制。许多程序设计问题都要求程序能够停下手头的工作,改为处理其他一些问题,再返回主进程。可以通过多种途径达到这个目的。最开始的时候,那些拥有机器低级知识的程序员编写一些“中断服务例程”,主进程的暂停是通过硬件级的中断实现的。尽管这是一种有用的方法,但编出的程序很难移植,由此造成了另一类的代价高昂问题。有些时候,中断对那些实时性很强的任务来说是很有必要的。但还存在其他许多问题,它们只要求将问题划分进入独立运行的程序片断中,使整个程序能更迅速地响应用户的请求。在一个程序中,这些独立运行的片断叫作“线程”(Thread),利用它编程的概念就叫作“多线程处理”。多线程处理一个常见的例子就是用户界面。利用线程,用户可按下一个按钮,然后程序会立即作出响应,而不是让用户等待程序完成了当前任务以后才开始响应。最开始,线程只是用于分配单个处理器的处理时间的一种工具。但假如操作系统本身支持多个处理器,那么每个线程都可分配给一个不同的处理器,真正进入“并行运算”状态。从程序设计语言的角度看,多线程操作最有价值的特性之一就是程序员不必关心到底使用了多少个处理器。程序在逻辑意义上被分割为数个线程;假如机器本身安装了多个处理器,那么程序会运行得更快,需作出任何特殊的调校。根据前面的论述,大家可能感觉线程处理非常简单。但必须注意一个问题:共享资源!如果有多个线程同时运行,而且它们试图访问相同的资源,就会遇到一个问题。举个例子来说,两个进程不能将信息同时发送给一台打印机。为解决这个问题,对那些可共享的资源来说(比如打印机),它们在使用期间必须进入锁定状态。所以一个线程可将资源锁定,在完成了它的任务后,再解开(释放)这个锁,使其他线程可以接着使用同样的资源。Java的多线程机制已内建到语言中,这使一个可能较复杂的问题变得简单起来。对多线程处理的支持是在对象这一级支持的,所以一个执行线程可表达为一个对象。JaVa也提供了有限的资源锁定方案。它能锁定任何对象占用的内存(内存实际是多种共享资源的一种),所以同一时间只能有一个线程使用特定的内存空间。为达到这个目的,需要使用synchronized关键字。其他类型的资源必须由程序员明确锁定,这通常要求程序员创建一个对象,用它代表一把锁,所有线程在访问那个资源时都必须检查这把锁。1.10永久性创建一个对象后,只要我们需要,它就会一直存在下去。但在程序结束运行时,对象的“生存期”也会宣告结束。尽管这一现象表面上非常合理,但深入追究就会发现,假如在程序停止运行以后,对象也能继续存在,并能保留它的全部信息,那么在某些情况下将是一件非常有价值的事情。下次启动程序时,对象仍然在那里,里面保留的信息仍然是程序上一次运行时的那些信息。当然,可以将信息写入一个文件或者数据库,从而达到相同的效果。但尽管可将所有东西都看作一个对象,如果能将对象声明成“永久性”,并令其为我们照看其他所有细节,无疑也是一件相当方便的事情。Java1.1提供了对“有限永久性”的支持,这意味着我们可将对象简单地保存到磁盘上,以后任何时间都可取回。之所以称它为“有限”的,是由于我们仍然需要明确发出调用,进行对象的保存和取回工作。这些工作不能自动进行。在Java未来的版本中,对“永久性”的支持有望更加全面。1.11Java和因特网既然Java不过另一种类型的程序设计语言,大家可能会奇怪它为什么值得如此重视,为什么还有这么多的人认为它是计算机程序设计的一个里程碑呢?如果您来自一个传统的程序设计背景,那么答案在刚开始的时候并不是很明显。Java除了可解决传统的程序设计问题以外,还能解决trldWdeWeb(万维网)上的编程问题。1.11.1什么是web?veb这个词刚开始显得有些泛泛,似乎“冲浪”、“网上存在”以及“主页”等等都和它拉上了一些关系。甚至还有一种nternet综合症”的说法,对许多人狂热的上网行为提出了质疑。我们在这里有必要作一些深入的探讨,但在这之前,必须理解客户机/服务器系统的概念,这是充斥着许多令人迷惑的问题的又一个计算领域。1.客户机/服务器计算客户机/服务器系统的基本思想是我们能在一个统一的地方集中存放信息资源。一般将数据集中保存在某个37
±Ǟ ڄʟԝʌÌęۗ~Ȁʋ½ŮǬЀ̀ӢՋӑơƦȀ҉֑ʨؤ̯ۓbצƦęרҹʟֆԼƒؔѰęרϹȔՈ֣ӫ ՒŮȆܜ~ǫյĴ͠пԦ׆ֆԼ~ڃƹɸۧ˥ęb̧ؤՊȵƦۜ˶ŕŪڬȀϪŮbܖ̚әŮӑɔ~ϭ׆ مٓʌшŲʙۀӕŮę٭רÌ׆fۗƞǛ֑ͦęg~ۧ˥ęŮڅՈӢՊȵكʾʙŮۗƞӔ֬Ůb˨Ȧڬ ӢًٓۜŮƽƲ~ŢÌĮŮęרɌϳۅؠُ~ńڊėͺΉ͛ŮśʫǵֆԼb ٓ׆ӑɔ~ۗƞơϭ׆ӔӑםɌћŮ҉֑͊ԈӢɌٓÉؔŮbŢɬŐڄпԦצƦֆԼ~ԧφۋؔѰ˃ֆԼɤ NJ˥ҔƔͧךٽŮęרЧƞۗ~ӘڶȀęרϹȅԙŶַؽًɞŮѬѰbڄȀęר~ۗ׆ڬƔͧךٽŮЧ ƞˎܜfְęgz5HR EAD{~ًͥԧÌęŮǬЀ̀ˎܜfƦְęĴ͠gbƦְęĴ͠ȀąʻŮͦ܇̀Ӣً ɞ˜ϑbְًͥę~ًɞ̧֣ȀЇ~ѿɕęרɼͧʘܜĮַؽ~ƬáӢ҂ًɞűŜęרէėͺťє҉ ֑ؤɕé̚әַؽb ܖ̚ә~ְęۋӢًٙNJМşȀĴ͠шŮĴ͠ӑʰŮۜȆ̋bŢʪғòܜ֟Վ½ҼڿĞƦȀĴ͠ш~ϭμ ρȀְęƒ̧NJМȂȀáՋŮĴ͠ш~ڷڭ˥Ҕf×ٽךԝg۷ԫbʼnęרҹʟ٠Ůˋƙ̞~Ʀְęò ܖܜٓʫۇŮԷہם̀Ӣę٭רáÉȢהŪŵӘًͺƦұȀĴ͠шbęڄרΤʓدجҮ¼NJǼյӾȀְ ęʪғʌш½Ҽ۴ͺƦȀĴ͠ш~ϭμęרɼךٽŭȅ̷~ܜףĮ҉ɅԷӱŮƃ׃b ȃ̉єϑŮӺ~Řʧ̧ϹDZְ̒ęĴ͠DŽąʵşbŢÉץ۬جȀֆԼȎָٯ܂wғȳٓƦȀְęՋӑ ךٽ~ƬѢԧφөՖǂֆֱՋŮٯ܂̀~ɼ٢ŪȀֆԼb̅Ȁͦ܇͊Ԉ~ʹȀ˥ęáϹ˃ו֘ՋӑưԕȂ ԩŗػʌbյ˙̓ڬȀֆԼ~ơϭ׆̧ȎָŮٯ܂͊ԈzÁғŗػʌ{~ԧφڄӘًлʰÉץ˥ҔԤƇ۷ ԫbԥؤȀְę̧˃ٯ܂ԤƇ~ڄէėͺԧŮ҉֑ɕ~ڃ̚˙zӤǃ{ڬȀԤ~ӘпԦְę̧ؤː܀Әً ՋؑŮٯ܂b +AVAŮƦְęʌأۓϸ˂Ū٠ۗ~ڬӘȀ̧ϹˍǢٿŮֆԼÎŭʵşу͊bơƦְęĴ͠ŮڿĞӢڄơ ֽڬʙڿĞŮ~ԥؤȀךۆְę̧ÓŕյȀơֽb+AVAؗԻȊͺٓ֯Ůٯ܂ԤƇƽbԧϹԤƇ҉Ʌ ơֽڛًŮϸŐzϸŐӔʢӢƦۜȎָٯ܂Ů~}ۜԥؤՋӑʰۋϹٓȀְęӘًԷƇŮϸŐ̭ʰb յŕŪڬȀϪŮ~ףؔӘًS YNCHR ONI ZEDȢʼ܉bпԦ͛טŮٯ܂Éץُę٭רϙѽԤƇ~ڬՊąؔѰęר ٭Ļ˂Ȁơֽ~ًԧśÓԤ~ԥְٓęڄǂֆϭȀٯ܂ӑƒÉץʴüڬԤb ȍĘǯ Ļ˂Ȁơֽɕ~ۋؔևφף̀ԧ~ؔɼۄŐڄ֣ѷbŢڄęר˘Ӽךٽӑ~ơֽŮfӃŐлgؗɼǹ ˘Ӽb˨Ȧڬֽ֬ÓϑҮDŽąɆ͠~ŢҽҔ۸˻̀ɼư֬~ʪғڄęרՈؤךٽۊɕ~ơֽؗϹʣŐ ڄ×~Ϲ°ԧŮѺåו~֘ϭμڄϧ׆ѫ̼֣˃ӢʾDŽąٓʫۇŮӟѫb֣ņцƍęרӑ~ơֽҍѿڄ ϭ͡~͡ϑ°Ůו֘ҍѿӢęרҮņךٽӑŮϭו׆֘bťѿ~̧ؤ˃ו֘ҔȀփʾʅګӾ̳̉~ ʼnƬŕŪֱՋŮׅȳbŢ˨Ȧ̧˃ԥٓƊ֔ƒ̞ܜȀơֽ~ғȳϹ˃ơֽӂϙėfي˽םg~×Ίпյև φڧ̞пԦԥ֢ٓ˔~֊ءؗӢʾֱťƽÍŮӟѫb +AVA ԻȊͺơfٓ֯ي˽םgŮڿĞ~جڬռ܀ևφ̧˃ơֽʵşŶ°ŐŪŁГҮ~ؤɕ҉Ʌӑʰƒ̧ ѵɸbہԥؤĖԧյfٓ֯gŮ~ӢُٙևφҍѿףؔϙѽưĮƃً~˥ךơֽٰŐɄѵɸȆܜb׆ڬȆ ܜáϹ܈ƍ˥ךbڄ+AVAջ͊Ů£½ۗ~ơfي˽םgŮڿĞٓլȅʨѺϑb /D/ áȈƵDŽ ʡѿ+AVAáȵΉ͛ۜטŮęרҹʟ٠~Řʧ̧ϹɼрȡԧյӒμۇŭғń۞Ө~յӒμɬٓڬμƦŮ҇ ҊյԧӢʟԝʌęרҹʟŮȀ͡ęµϷ ғȳЃ͊܈ȀĶՎŮęרҹʟ¸˰~ϭμŖڄdz̚әŮӑɔ ×áӢɌϙ֪b+AVAįͺ̧˙̓ĶՎŮęרҹʟֆԼؤդ~ɬϹ˙̓8OR L D 8I DE 8EBzընթ{ҮŮÌęֆ Լb ƐōƘ *30T 8EBڬȀŃdz̚ә֪ŭٓ׆ƼƼ~ԓɗfĦ͓gafթҮŐڄgؤʖfؘۧgűűƒɄԧ͈Үͺ׆Ȣ֟b Ӏېɬٓۜf* NT ER NET ܌ɆںgŮԈƲ~ơצƦ̺҇҆ŮҮթךյԻĮͺءەbևφڬڄٓ͡Éؔ׆ܜ ҽҔŮԵ~Ţہڬڄє~Éץ̪˙͠ɞʌǛ֑ш֟ՎŮǬЀ~ڬӢĥĤצ܀ƦΊ҇ϊʆŮֆԼŮٗȀ ʟԝΈ١b ̪ɞʌǛ֑шʟԝ ̪ɞʌǛ֑ш֟ՎŮʋ½ԍֶӢևφϹڄȀՎŮŶƽʕۗŐǃו֘ٯ܂b˃¡Ӿ̉ʕۗ°ŐڄϧȀ
数据库中,根据其他人或者机器的请求将信息投递给对方。客户机/服务器概述的一个关键在于信息是“集中存放”的。所以我们能方便地更改信息,然后将修改过的信息发放给信息的消费者。将各种元素集中到一起,信息仓库、用于投递信息的软件以及信息及软件所在的那台机器,它们联合起来便叫作“服务器(Server)。而对那些驻留在远程机器上的软件:它们需要与服务器通信,取回信息,进行适当的处理,然后在远程机器上显示出来,这些就叫作“客户”(Cient)。这样看来,客户机/服务器的基本概念并不复杂。这里要注意的一个主要问题是单个服务器需要同时向多个客户提供服务。在这一机制中,通常少不了一套数据库管理系统,使设计人员能将数据布局封装到表格中以获得最优的使用。除此以外,系统经常允许客户将新信息插入一个服务器。这意味着必须确保客户的新数据不会与其他客户的新数据冲突,或者说需要保证那些数据在加入数据库的时候不会丢失(用数据库的术语来说,这叫作“事务处理”)。客户软件发生了改变之后,它们必须在客户机器上构建、调试以及安装。所有这些会使问题变得比我们一般想象的复杂得多。另外,对多种类型的计算机和操作系统的支持也是一个大问题。最后,性能的问题显得尤为重要:可能会有数百个客户同时向服务器发出请求。所以任何微小的延误都是不能忽视的。为尽可能缓解潜伏的问题,程序员需要谨慎地分散任务的处理负担。一般可以考虑让客户机负担部分处理任务,但有时亦可分派给服务器所在地的其他机器,那些机器亦叫作“中间件”(中间件也用于改进对系统的维护)。所以在具体实现的时候,其他人发布信息这样一个简单的概念可能变得异常复杂。有时甚至会使人产生完全无从着手的感觉。客户机/服务器的概念在这时就可以大显身手了。事实上,大约有一半的程序设计活动都可以采用客户机/服务器的结构。这种系统可负责从处理订单及信用卡交易,一直到发布各类数据的方方面面的任务一股票市场、科学研究、政府运作等等。在过去,我们一般为单独的问题采取单独的解决方案:每次都要设计一套新方案。这些方案无论创建还是使用都比较困难,用户每次都要学习和适应新界面。客户机/服务器问题需要从根本上加以变革!2.veb是一个巨大的服务器web实际就是一套规模巨大的客户机/服务器系统。但它的情况要复杂一些,因为所有服务器和客户都同时存在于单个网络上面。但我们没必要了解更进一步的细节,因为唯一要关心的就是一次建立同一个服务器的连接,并同它打交道(即使可能要在全世界的范围内搜索正确的服务器)最开始的时候,这是一个简单的单向操作过程。我们向一个服务器发出请求,它向我们回传一个文件,由于本机的浏览器软件(亦即“客户”或“客户程序”)负责解释和格式化,并在我们面前的屏幕上正确地显示出来。但人们不久就不满足于只从一个服务器传递网页。他们希望获得完全的客户机/服务器能力,使客户(程序)也能反馈一些信息到服务器。比如希望对服务器上的数据库进行检索,向服务器添加新信息,或者下一份订单等等(这也提供了比以前的系统更高的安全要求)。在Veb的发展过程中,我们可以很清晰地看出这些令人心喜的变化。veb浏览器的发展终于迈出了重要的一步:某个信息可在任何类型的计算机上显示出来,母需任何改动。然而,浏览器仍然显得很原始,在用户迅速增多的要求面前显得有些力不从心。它们的交互能力不够强,而且对服务器和因特网都造成了一定程度的于扰。这是由于每次采取一些要求编程的操作时,必须将信息反馈回服务器,在服务器那一端进行处理。所以完全可能需要等待数秒乃至数分钟的时间才会发现自已刚才拼错了一个单词。由于浏览器只是一个纯粹的查看程序,所以连最简单的计算任务都不能进行(当然在另一方面,它也显得非常安全,因为不能在本机上面执行任何程序,避开了程序错误或者病毒的骚扰)为解决这个问题,人们采取了许多不同的方法。最开始的时候,人们对图形标准进行了改进,使浏览器能显示更好的动画和视频。为解决剩下的问题,唯一的办法就是在客户端(浏览器)内运行程序。这就叫作“客户端编程”,它是对传统的“服务器端编程”的一个非常重要的拓展。1.11.2客户端编程(注释)Web最初采用的“服务器一浏览器”方案可提供交互式内容,但这种交互能力完全由服务器提供,为服务器和因特网带来了不小的负担。服务器一般为客户浏览器产生静态网页,由后者简单地解释并显示出来。基本HIM语言提供了简单的数据收集机制:文字输入框、复选框、单选钮、列表以及下拉列表等,另外还有一个按钮,只能由程序规定重新设置表单中的数据,以便回传给服务器。用户提交的信息通过所有Web服务器均能支持的“通用网关接口”(CG)回传到服务器。包含在提交数据中的文字指示CG该如何操作。最常见的行动是运行位于服务器的一个程序。那个程序一般保存在一个名为“cg-bin的目录中(按下veb页内的个按钮时,请注意一下浏览器顶部的地址窗,经常都能发现“gi-bin的字样)。大多数语言都可用来编制这些程序,但其中最常见的是Perl。这是由于Per是专为文字的处理及解释而设计的,所以能在任何服务器上安装和使用,无论采用的处理器或操作系统是什么。38
Ӿ̳̉ۗ~ȃ̉пԦ҇ʅګʌшŮѬѰ˃ו֘ՑŹȂơƽb̪ɞʌǛ֑шǬӺŮȀȢʼڄٙו֘Ӣfʕ ۗŐǃgŮbԥؤևφϹƽÍŶȅǫו~֘ѿɕ˃סǫȵŮו֘ưǃȂו֘ŮֿLjګb˃ȁۜ٪ԘʕۗŪ у~ו֘ð̳aًٙՑŹו֘Ůҕʾؤʖו֘ʖҕʾԥڄŮϭԩʌш~ԧφͫɆу͊ÍˎܜfǛ֑шg z4ER VER {bƬơϭۮ׆ٱڄęʌшҮŮҕʾ~ԧφףٟؔǛ֑шՊו~ѵɸו˥~֘ךӣťŮĴ͠~ѿ ɕٱڄęʌшҮ֪ӛĮ͊~׆ڬˎ̀ܜf̪ɞgz$L I ENT {b ڬ̪~̞͊ؑɞʌǛ֑шŮʋ½ǬЀ×áǢٿbڬ۬ؔ͡جŮȀۧؔֆԼӢşȀǛ֑шףؔՋӑּƦȀ ̪ɞԻȊǛ֑bڬڄʌۓ~ۗՊąұáͺԶӾ̳̉Ȧ֟͠Վ~Әҹʟ҇٭Ϲ˃Ӿ̉ẫǏ۴ŪÓǾۗ~ ؤʄŭܖٌŮӘًbįńؤդ~֟Վ˭ąצټ̪ɞ˃וד֘úҔȀǛ֑шbجڬռ܀Éץѽ°̪ɞŮדӾ ̉áɼٟпԦ̪ɞŮדӾ̉ĦՕ~ʅګԈף°ؔڼϭ׆Ӿ̉ڄʨҔӾ̳̉ŮӑɔáɼƉӌzًӾ̳̉Ůӹ٠ ͊Ԉ~ڬˎܜfӟ֑Ĵ͠g{b̪ɞҕʾưӃͺǫÎہɕ~ԧφÉڄץ̪ɞʌшҮȒ˂aƃөؤʖ۴bԥ ٓ׆ڬɼӘֆԼÎŭÁևφֶֽ¡ŮǢٿŭƦbΉդ~ơƦۜ͛טŮʟԝʌɄòܜ֟ՎŮڿĞؗӢȀŘ ֆԼbܖɕ~םϹŮֆԼ֪ŭَյ۞̧ؔϹɼٓӾȀ̪ɞՋӑּǛ֑шưĮѬѰbԥؤ҉ɅհׂŮ֒ ƒӢáϹɘӨŮbյ˨̧Ϲɭ˙ѕǙŮֆԼ~ęף٭רؔˤӁŶNJҜ҉֑ŮĴ͠ǥŞb̧¡ؤ̠Ι҂̪ɞ ʌǥŞåNJĴ͠҉֑~Ţٓӑت̧NJВȂǛ֑шԥڄŶŮпԦʌш~ϭ׆ʌшتˎܜfۗʰʾgzۗʰʾؗ ًٙǫ˥ơ֟ՎŮնɜ{b ԥڄؤ̋ԽӔ֬Ůӑɔ~пԦ҇ưâו֘ڬؑȀʵşŮǬЀ̧ϹÎŭشąǢٿbٓӑӀېɼӘ҇āӃէѺ ֊ʼn܀ӫŮDZ̒b̪ɞʌǛ֑шŮǬЀڬڄӑ̧̀ؤŘ֪ҼӫͺbӟӔҮ~Řاٴٓ¦Ůęרҹʟʁƍƒ ̧ؤëً̪ɞʌǛ֑ш٢Ȓbڬ֟ۜՎ̧ǥڌʼnĴ͠ƈşʖוˈً̙ا~ۄŪưâȁ͛Ӿ̉Ůƽƽϑ ϑŮ҉֑ccșЩӦăḁװ˻aڸǞܜٽűűbڄȵѷ~ևφ¡յşƔŮֆԼëѵşƔŮ˙̓ƽ ρņƒؔҹʟԶדƽb׆ڬƽ֊Ļ˂ɬӢӘًƒÁˍ̓ϳ~ًɞρņƒؔװ֜Ʉӣדؽ˜ϑb̪ɞ ʌǛ֑шֆԼףؔʼnȃ½ҮʨؤÎǽw 8EBӢȀ̊ŘŮǛ֑ш 8EBӔʢ̀ӢԶȬϝ̊ŘŮ̪ɞʌǛ֑ш֟ՎbŢԧŮѫ̼ؔǢ׆ٿ~ضյԥٓǛ֑шɄ̪ɞƒՋӑ ŐڄٙşȀթΦҮϑbŢևφξÉؔͺ˙ȅ˥ãŮ֢˔~ضյմؔȢהŮ̀Ӣņ˂ͧՋȀǛ֑шŮ ͬː~×ՋԧŗˈūzʘӘ̧ϹؔڄѺӝ˜ŮƺճϸԖԣڷѽŮǛ֑ш{b ܖ̚әŮӑɔ~ڬӢȀʵşŮşּòܜȵębևφּȀǛ֑шưĮѬѰ~ԧּևφɸĶȀփʾ~ُٙ ½ʌŮܫ͏шҕʾzتʘf̪ɞgʅf̪ɞęרg{ǥڌ˙ӤɄǾӚɥ~×ڄևφϑєŮбϩҮڷѽŶ֪ӛ Į͊bŢ҇φá˽̀áΰܑٙۋʼnȀǛ֑шĶŹթؘbԦφ֙լʄŭէѺŮ̪ɞʌǛ֑шϹͩ~Ә̪ɞ zęרؗ}ϹƸ̿ו׆֘ŪǛ֑шbÁғ֙լơǛ֑шҮŮӾ̳̉˥ךʴԣ~ּǛ֑шՁʨוד~֘ʅګ ֣ǍƈşűűzڬؗԻȊͺÁؤєŮ֟ՎȅǵŮѺؔѰ{bڄ8EBŮưڙȵęۗ~ևφ̧ؤɌѩ֕Ŷ̞ Į׆ڬΊ҇ה֝ŮÎɥb 8EBܫ͏шŮưڙٙۛίĮͺ۞ؔŮãϧȀו̧֘ڄ҉Ʌ͛טŮʟԝʌҮ֪ӛĮ͊~ף҉Ʌǫƍbѿ Ƭ~ܫ͏шҍѿ֪ŭɌ٫ә~ڄًɞԙڐƦŮؔѰϑє֪ŭٓ׆dáʼnהbԧφŮˈɝϹͩáȔћ~ƬѢ ơǛ֑шɄضԷթƒڊėͺƇęƙŮǮ҃bڬӢُٙρņëѵ׆ؔѰÌęŮòܜӑ~Éץ˃ו֘Ƹ̿ɸ Ǜ֑ш~ڄǛ֑шϭƛ˥ךĴ͠bԥؤէѺ̧ϹףؔűŜӾϔϯېӾNJۙŮӑʰéɼư֬܈ʜdzéЪŔͺ ȀşŃbُٙܫ͏шۋӢȀĽŏŮü̞ęר~ԥؤrܖʵşŮʟԝ҉֑ƒáϹ˥ךzťѿڄΉƽϑ~ ԧ֪ؗŭDŽąѺ~ضյáϹڄ1/2ʌҮϑךۆ҉Ʌęר~Ê̚ͺęרŔ֒ʅګÖƓŮҞ҃{b յ˙̓ڬȀֆԼ~҇φëѵͺצƦáՋŮƽƲbܖ̚әŮӑɔ~҇φơՖיÒۼ˥ךͺǫ˥~Әܫ͏шϹ֪ ӛȅɀŮƍɣɄӨЫbյ˙̓ӈ֣ŮֆԼ~մ٧Ʋ̀Ӣڄ̪ɞƛzܫ͏ш{ϸךٽęרbڬˎ̀ܜf̪ ɞƛÌęg~ԧӢơĶՎŮfǛ֑шƛÌęgŮȀDŽą۞ؔŮբڙb ĥådQȼƙOR 8EBܖĭëًŮfǛ֑шܫ͏шgƽ̧ԻȊˈɝӚϸҐ~ŢڬˈۜɝϹͩէѺُǛ֑шԻȊ~յǛ֑ш ɄضԷթŚ͊ͺáׂŮǥŞbǛ֑ш¡յ̪ɞܫ͏шāӃ˲ԫթؘ~ُɕګʵşŶ˙Ӥ×֪ӛĮ͊bʋ½ )5.- ٠ԻȊͺʵşŮӾ̉Ӫʕʌۓfփ܉ӲҔ̻aǢׯ̻aşׯЇaͼÓؤʖ֣͈ͼÓű~ΉդɬٓȀ Ї~ۋϹُęרȬƇ۞דҹےÓşۗŮӾ̉~ؤÍɸĶȂǛ֑шbًɞԻˈŮו֘Պȵԥٓ8EBǛ֑ш̖ ϹڿĞŮfՊًթȢː̰gz$(* {ɸĶŪǛ֑шbȹڄԻˈӾ̉ۗŮփۉ܉ӛ$(* ǪғɅòܜbܖąʻŮ ךƍӢךٽվٙǛ֑шŮȀęרbϭȀęר°¡ŐڄȀϚյfCGI BI NgŮϪΔۗz֣ 8EBؘϸŮ ȀЇӑ~Ѭ۬ج֣ܫ͏шƆåŮŶۈĸ~˭ąƒϹư֬fCGI BI NgŮ܉}ؑbŘƦӾ٠ƒً̧͊Ìۓ ׆ڬęר~ŢпۗܖąʻŮӢ 1ER L bڬӢُٙ 1ER L Ӣ۱յփ܉ŮĴ͠ʖ˙ӤƬҹʟŮ~ԥؤϹڄ҉ɅǛ֑ шҮ۴ɄӘً~֊ëًŮĴ͠шʅòܜ֟ՎӢӒμb
?:本节内容改编自某位作者的一篇文章。那篇文章最早出现在位于wwwnainspringcom的Minspring上。本节的采用已征得了对方的同意。今天的许多Veb站点都严格地建立在Co的基础上,事实上几乎所有事情都可用Co做到。唯一的问题就是响应时间。程序的响应取决于需要传送多少数据,以及服务器和因特网两方面的负担有多重(而且C程序的启动比较慢)。veb的早期设计者并未预料到当初绰绰有余的带宽很快就变得不够用,这正是大量应用充斥网上造成的结果。例如,此时任何形式的动态图形显示都几乎不能连贯地显示,因为此时必须创建一个GF文件,再将图形的每种变化从服务器传递给客户。而且大家应该对输入表单上的数据校验有着深刻的体会。原来的方法是我们按下网页上的提交按钮(Subnnt);数据回传给服务器;服务器启动一个程序,检查用户输入是否有错;格式化一个HIM页,通知可能遇到的错误,并将这个页回传给我们;随后必须回到原先那个表单页,再输入一遍。这种方法不仅速度非常慢,也显得非常繁琐。解决的办法就是客户端的程序设计。运行Vb浏览器的大多数机器都拥有足够强的能力,可进行其他大量工作。与此同时,原始的静态HMI方法仍然可以采用,它会一直等到服务器送回下一个页。客户端编程意味着veb浏览器可获得更充分的利用,并可有效改善Veb服务器的交互(互动)能力。对客户端编程的讨论与常规编程问题的讨论并没有太大的区别。采用的参数肯定是相同的,只是运行的平台不同:web浏览器就象一个有限的操作系统。无论如何,我们仍然需要编程,仍然会在客户端编程中遇到大量问题,同时也有很多解决的方案。在本节剩下的部分里,我们将对这些问题进行一番概括,并介绍在客户端编程中采取的对策。1.插件朝客户端编程迈进的时候,最重要的一个问题就是插件的设计。利用插件,程序员可以方便地为浏览器添加新功能,用户只需下载一些代码,把它们“插入”浏览器的适当位置即可。这些代码的作用是告诉浏览器“从现在开始,你可以进行这些新活动了”(仅需下载这些插入一次)。有些快速和功能强大的行为是通过插件添加到浏览器的。但插件的编写并不是一件简单的任务。在我们构建一个特定的站点时,可能并不希望涉及这方面的工作。对客户端程序设计来说,插件的价值在于它允许专业程序员设计出一种新的语言,并将那种语言添加到浏览器,同时不必经过浏览器原创者的许可。由此可以看出,插件实际是浏览器的一个“后门”,允许创建新的客户端程序设计语言(尽管并非所有语言都是作为插件实现的)。2.脚本编制语言插件造成了脚本编制语言的爆炸性增长。通过这种脚本语言,可将用于自己客户端程序的源码直接插入HM页,而对那种语言进行解释的插件会在HTM页显示的时候自动激活。脚本语言一般都倾向于尽量简化,易于理解。而且由于它们是从属于HIM页的一些简单正文,所以只需向服务器发出对那个页的一次请求,即可非常快地载入。缺点是我们的代码全部暴露在人们面前。另一方面,由于通常不用脚本编制语言做过份复杂的事情,所以这个问题暂且可以放在一边。脚本语言真正面向的是特定类型问题的解决,其中主要涉及如何创建更丰富、更具有互动能力的图形用户界面(GI)。然而,脚本语言也许能解决客户端编程中80%的问题。你碰到的问题可能完全就在那80%里面。而且由于脚本编制语言的宗旨是尽可能地简化与快速,所以在考虑其他更复杂的方案之前(如JaVa及ActiveX,首先应想一下脚本语言是否可行。目前讨论得最多的脚本编制语言包括Javcsaipt(它与Java没有任何关系;之所以叫那个名字,完全是一种市场策略)VBSaipt(同VsudBasic很相似)以及Td/Tk(来源于流行的跨平台构造语言)。当然还有其他许多语言,也有许多正在开发中。JavaSaript也许是目常用的,它得到的支持也最全面。无论Nets aapeNbvigatar,MaosoftInternetExparer,还是Qpera,目前都提供了对Javcsaipt的支持。除此以外,市面上讲述Javasaipt的书籍也要比讲述其他语言的书多得多。有些工具还能利用JavcSaipt自动产生网页。当然,如果你已经有MsudBcsic或者Td/Tk的深厚功底,当然用它们要简单得多,起码可以避免学习新语言的烦恼(解决Web方面的问题就已经够让人头痛了)。3.Java如果说一种脚本编制语言能解决80%的客户端程序设计问题,那么剩下的20%又该怎么办呢?它们属于一些高难度的问题吗?自前最流行的方案就是Java。它不仅是一种功能强大、高度安全、可以跨平台使用以及国际通用的程序设计语言,也是一种具有旺盛生命力的语言。对Java的扩展是不断进行的,提供的语言特性和39
t½˔ϸҐǫÌ܈ϧվګܜŮХփڞbϭХփډܖڞĮ֬ڄվٙ WWW MAI NSPR I NG COMŮ .AI NSPR I NG Үb½˔ŮëًڴأŭͺơƽŮՋجb ˡՀŮצƦ 8EBڝżƒǾŶ˂ͧڄ *)$ŮʋıҮ~ӟӔҮʛɗԥٓӟѫƒً̧ $(* ܛŪbմŮֆԼ̀Ӣ ַؽӑʰb$(* ęרŮַؽѵ̓ٙףؔĶԕƦұӾ̉~ؤʖǛ֑шɄضԷթʹƽϑŮǥŞٓƦ۞zƬѢ$(* ęרŮцƍÁˍα{b8EBŮډлҹʟګ×ջ٩ͻŪťĭĿĿٓٛŮŚ̸Ɍ̷̀ÎŭáȔً~ڷڬӢŘͶؽ ًĥĤթҮڊė٢ȳbͦғ~ńӑ҉ɅיӚŮƍԫՖי֪ӛƒʛɗáϹͬȩŶ֪ӛ~ضյńӑÉץĻ˂ Ȁ(* ' փʾ~ڃ˃ՖיŮρۜÎɥʼnǛ֑шĶŹȂ̪ɞbƬѢŘʧؽǪơӲҔÓşҮŮӾ̉׃ٓ؊܀ҽ̩Ů Խɼb٫͊ŮƽƲӢևφ֣թؘҮŮԻˈЇz4UBMI T {Ӿ̉ɸĶȂǛ֑шǛ֑шцƍȀ $(* ę ר~ʴüًɞӲҔӢǕٓŔǾӚɥȀ )5.- ؘ~Պۀ̧Ϲ٢ŪŮŔ֒~×˃ڬȀؘɸĶȂևφԟɕÉץ ɸŪ٫֥ϭȀÓşؘ~ڃӲҔÑbڬۜƽƲáˣԙƙDŽąα~֪ؗŭDŽąƵԢb ˙̓٧Ʋ̀Ӣ̪ɞƛŮęרҹʟbךٽ 8EBܫ͏шŮŘƦӾʌшƒمܑٓȔћŮϹͩ~̧˥ךпԦŘͶȆ ܜbٟńՋӑ~٫әŮ˲ԫ)5.- ƽƲҍѿ̧ؤëً~ԧɼۄűŪǛ֑шԕɸ֣Ȁؘb̪ɞƛÌęجռ܀ 8EBܫ͏ш̧ʄŭȅĥNJŮًͥ~×̧ׅٓǫҪ8EBǛ֑шŮˈɝzɝƍ{Ϲͩb ơ̪ɞƛÌęŮԵٟąȬÌęֆԼŮԵ×ξٓԪŘŮѲÔbëًŮîӾ̬ƇӢֱՋŮ~ۋӢךٽŮЮԩ áՋ8EBܫ͏шֽ̀Ȁٓ֯Ůòܜ֟Վb֊ғɅ~ևφҍѿףؔÌę~ҍѿɼڄ̪ɞƛÌęۗ٢ŪŘ ͶֆԼ~ՋӑؗٓɌƦ˙̓Ůƽbڄ˔1/2ӈ֣ŮåNJ͡~ևφ˃ơ׆ڬֆԼ˥ךƳǬ̈́~×˞Ҳڄ̪ɞ ƛÌęۗëѵŮơõb úʾ Č̪ɞƛÌęί˥Ůӑɔ~ܖؔ۞ŮȀֆԼ̀ӢúʾŮҹʟbًͥúʾ~ę٭ר̧ؤƽÍŶյܫ͏шՁʨ דȈϹ~ًɞףۋ֣׆ڂśΩ~ԧφfúҔgܫ͏шŮӣťվےʘ̧b׆ڬśΩŮܜًӢǹԜܫ͏ш fʼn֬ڄ̚ә~ϼ̧ؤ˥ד׆ڬךʁƍͺgzˣף֣׆ڬڂúҔņ{bٓ׆̷ԙɄȈϹћŘŮךյӢՊȵ úʾՁʨŪܫ͏шŮbŢúʾŮÌ×áӢʾʵşŮ҉֑bڄևφȒ˂ȀԷƇŮڝżӑ~̧Ϲ×á֙լ ҷʖڬƽϑŮȆܜbơ̪ɞƛęרҹʟ͊Ԉ~úʾŮʫڄۇԧٙצټ۱ؙę٭רҹʟĮۜדŮ٠~×˃ ϭۜ٠ՁʨŪܫ͏ш~ՋӑáÉ˭ȵܫ͏ш٫ĻګŮצ̧bُņ́ؤ̞Į~úʾӔʢӢܫ͏шŮȀfɕ τg~צټĻ˂דŮ̪ɞƛęרҹʟ٠z˨Ȧ×DŽԥٓ٠ƒӢܜյúʾӔ֬Ů{b ˊ½Ìۓ٠ úʾڊėͺˊ½Ìۓ٠Ů´ڐםڔĆbՊȵڬ1/2ˊۜ٠~̧˃ًٙ܈ʜ̪ɞƛęרŮٯΩۄːúҔ )5.- ؘ~Ƭơϭۜ٠˥ך˙ӤŮúʾɼڄ( 5.- ؘ֪ӛŮӑɔ܈ƍʏʁbˊ½٠¡ƒѨּٙ˨Ͷʵɥ~اٙ ͠˙bƬѢُٙԧφӢʼnӸٙ )5.- ؘŮ׆ʵşڷփ~ԥףۋؤּǛ֑шưĮơϭȀؘŮņѬѰ~ʘ̧DŽ ą̷ŶڂҔbѻżӢևφŮśΩѺå³Βڄ҇φϑєbΉƽϑ~ُٙՊąáًˊ½Ìۓ٠ܛȵǍǢٿŮ ӟѫ~ԥڬؤȀֆԼڅѢ̧ؤǃڄËb ˊ½٠ڷڭϑּŮӢԷƇ͛טֆԼŮ˙̓~пۗۧؔҷʖғɅĻ˂ȅǎǦaȅ̋ٓɝƍϹͩŮՖיًɞ˜ ϑz(6* {bѿƬ~ˊ½٠ؗצϹ˙̪̓ɞƛÌęۗ xŮֆԼbϼПŪŮֆԼ̧ϹէѺ̀ڄϭ x͡ ϑbƬѢُٙˊ½Ìۓ٠Ůی܋Ӣ˨̧ϹŶʵɥ̷ٟԙ~ԥڄؤ̠ΙпԦȅǢٿŮƽہєzғ+AVAʖ "CT I VE9{~Ӭ֥ؽֶ1/2ˊ֣٠ӢǕ̧ךb ϪєԵŭܖƦŮˊ½Ìۓ٠̈́+AVA4CR I PT zԧٟ+ AVAξٓ҉ɅȢ֟ہԥؤˎϭȀϚ܉~էѺӢ ۜӦăõΟ{a7#4CR I PT zՋ7I S UAL #AS I CɌֱԓ{ؤʖ5CL 5Kz͊ٯٙΌךŮ̵Юԩ (6* Ȓڊ٠{b ťѿɬٓпԦצƦ٠~ؗٓצƦڄڷ̚ưۗb +AVA4CR I PT ؗצӢϪąًŮ~ԧŭŪŮڿĞؗܖѺϑb֊ /ET S CAPE/AVI GAT OR~.I CR OS OF T * NT ER NET &XPL OR ER ~ɬӢ 0PER A~ϪєƒԻȊͺơ +AVA4CR I PT ŮڿĞbįńؤդ~ӦϑҮ˅Ӻ+AVA4CR I PT Ůӵʔؗ ؔÁ˅ӺпԦ٠ŮӵƦŭƦbٓ׆Ȇ̋ɬϹًͥ +AVA4CR I PT ܈ƍāӃթؘbťѿ~ғȳϼأ ٓ˭7I S UAL #AS I Cʅګ5CL 5K ŮҽɓȈŵ~ťѿًԧφؔʵşŭƦ~уΩ̧ؤÊϐװ֜ד٠ŮƷ϶z˙̓8EBƽϑŮ ֆԼ̀أ˭Ȕ҂҇ՒՏͺ{b +AVA ғȳԈ1/2ˊۜÌۓ٠Ϲ˙̓xŮ̪ɞƛęרҹʟֆԼ~ϭμӈ֣ŮxٗǪڏμ§Ϸ ԧφӸٙ׆ ǵϳƙŮֆԼΫ ϪєܖΌךŮƽ̀Ӣ +AVAbԧáˣӢۜȈϹћŘaǵƙѺa̧ؤ̵ЮԩӘًؤʖȲ ʢՊًŮęרҹʟ٠~ؗӢٓ̋ۜիӇӃϛͩŮ٠bơ +AVAŮͅڙӢáƞ˥ךŮ~ԻȊŮ٠ԷםɄ