还剩9页未读,继续阅读
本资源只提供10页预览,全部文档请下载后查看!喜欢就下载吧,查找使用更方便
文本内容:
第三章J__a程序设计基础
3.1J__a编程概况 现在你可以复习一下J__a语言的背景材料,它的基本结构象C/C++,但任何用面向过程语言编写过程序的人都可以了解J__a语言的大部分结构. J__a语言的源程序代码由一个或多个编译单元compilationunit组成,每个编译单元只能包含下列内容空格和注释除外*一个程序包语句packagestatement*入口语句importstatements*类的声明classdeclarations*界面声明inte_____declarations每个J__a的编译单元可包含多个类或界面,但是每个编译单元最多只能有一个类或者界面是公共的J__a的源程序代码被编译reg;后,便产生了J__a字节代码J__a的字节代码由一copy;不依赖于机器的指令组成,这copy;指令能被J__a的运行系统runtimesystem有效地解释J__a的运行系统工作起来如同一台虚拟机在当前的J__a实现中,每个编译单元就是一个以.j__a为后缀的文件每个编译单元有若干个类,编译后,每个类生成一个.class文件.class文件是J__a虚拟机能够识别的代码 三种类型如下://注释一行/*一行或多行注释*//**文档注释**/文档注释一般放在一个变量或函数定义reg;前指示在任何自动生成文档系统中调入这copy;注释都是声明条目的描述. 变量,函数,类和对象的名称都是标识符,程序员需要标识和使用的东西都需要标识符在J__a语言里标识符以字符或_$开头后面可以包含数字,标识符是大小写有区别的没有长度限制 有效的标识符mynameict_networkHello_sys_path$bill 例子inta_number;char_onechar;float$bill; 关键词abstractcontinuefornewswitchbooleandefaultgotonullsynchronizedbreakdoifpackagethisbytedoubleimplementsprivatethreadsafebyvalueelseimportprotectedthrowcaseextendsinstan__ofpublictransientcatchfalseintreturntruecharfinalinte_____shorttryclassfinallylongstaticvoidconstfloatnativesuperwhile其它保留词以下单词被保留使用castfuturegenericinneroperatorouterrestvar J__a使用五种基本类型:integer整数floating浮点数point指针Boolean布尔变量CharacterorString字符或字符串integer整数下边给出的数据表示都是整数的例子4,15,0__,0xAD00整数长度数据类型表示8bitsbyte16bitsshort32bitsint64bitslong floating浮点数下边给出的数据表示都是浮点数的例子
6.37,
3.7E15,3e8 浮点数长度数据类型表示32bitsfloat64bitsdouble Boolean布尔变量下边是布尔变量的两种可能取值truefalseCharacter字符下边给出的都是字符的例子a\\ttab\\uunicode String字符串下边给出的都是字符串的例子\Thisisastringliteral\\中国科学院计算所\数组你可以定义任意类型的数组.chars[];这是字符型数组;int[]array;这是整型数组;你还可以定义数组的数组.intblock[][]=newint
[2]
[3];数组边界在运行时被检测避免堆栈溢出和内存崩溃.在J__a里数组实际上是一个对象数组有一个成员变量length你可以用这个成员函数来查看任意数组的长度.inta[][]=newint
[10]
[3];a.length;/*10*/a
[0].length;/*3*/创建数组在J__a里创建数组你可使用两种基本方法一创建一个空数组intlist[]=newint
[50];或你可以用初始数值填充数组.Stringnames[]={\Chenji\\Yuan\\Chun\\Yang\};相当于下面功能:Stringnames[];names=newString
[4];names
[0]=newString\Chenji\;names
[1]=newString\Yuan\;names
[2]=newString\Chun\;names
[3]=newString\Yang\;在编译时你不能象下例那样创建静态数组intname
[50];//将产生一个编译错误你也不能用new操作去填充一个没定义大小的数组intname[];forinti=0;i9;i++{name[i]=i;} J__a语言的表达式和C语言非常类似运算符运算符operator优先级从高到底排列如下.[]++--!~instan__of*/%+-=\\==!=^||:=op=整数运算符在整数运算时,如果操作数是long类型,则运算结果是long类型,否则为int类型,绝不会是byte,short或char型这样,如果变量i被声明为short或byte,i+1的结果会是int如果结果超过该类型的取值范围,则按该类型的最大值取模单目整数运算符是运算符操作-单目非~位补码++加1--减1++运算符用于表示直接加1操作增量操作也可以用加运算符和赋值操作间接完成++lvalue(左值copy;表示lvalue+=1++lvalue也表示lvalue=lvalue+1只要lvalue没有副作用--运算符用于表示减1操作++和--运算符既可以作为前缀运算符,也可以做为后缀运算符双目整数运算符是运算符操作**+加-减*乘/除%取模位与|位或^位异或左移右移带符号添零右移整数除法按零舍入除法和取模遵守以下等式a/b*b+a%b==a整数算术运算的异常是由于除零或按零取模造成的它将引发一个算术异常下溢产生零,上溢导致越界例如加1超过整数最大值,取模后,变成最小值一个op=赋值运算符,和上表中的各双目整数运算符联用,构成一个表达式整数关系运算符,,=,=,==和!=产生boolean类型的数据 布尔运算符布尔boolean变量或表达式的组合运算可以产生新的boolean值单目运算符!是布尔非双目运算符&,|和^是逻辑AND,OR和XOR运算符,它们强制两个操作数求布尔值为避免右侧操作数冗余求值,用户可以使用短路求值运算符&&和||用户可以使用==和!=,赋值运算符也可以用=、|=、^=三元条件操作符:和C语言中的一样 浮点运算符浮点运算符可以使用常规运算符的组合如单目运算符++、--,双目运算符+、-、*和/,以及赋值运算符+=,-=,*=,和/=此外,还有取模运算%和%=也可以作用于浮点数,例如a%b和a-inta/b*b的语义相同这表示a%b的结果是除完后剩下的浮点数部分只有单精度操作数的浮点表达式按照单精度运算求值,产生单精度结果如果浮点表达式中含有一个或一个以上的双精度操作数,则按双精度运算,结果是双精度浮点数 数组运算符数组运算符形式如下[]可给出数组中某个元素的值合法的取值范围是从0到数组的长度减1取值范围的检查只在运行时刻实运算符以String对象实现运算符\+\完成并操作,如果必要则自动把操作数转换为String型如果操作数是一个对象,它可定义一个方法toString返回该对象的String方式,例如floata=
1.0print\Thevalueofais\+a+\\\n\;+运算符用到reg;上的例子Strings=\a=\+a;+=运算符也可以用于String注意,左边下例中的s1仅求值一次s1+=a;//s1=s1+a//若a非String型,自动转换为String型对象运算符双目运算符instan__of测试某个对象是否是指定类或其子类的实例例如ifmyO__ectinstan__ofMyClass{MyClassanothermyO__ect=MyClassmyO__ect;…}是判定myO__ect是否是MyClass的实例或是其子类的实例强制和转换J__a语言和解释器限制使用强制和转换,以防止出错导致系统崩溃整数和浮点数之间可以来回强制转换,但整数不能强制转换成数组或对象对象不能被强制为基本类型 下面几个控制结构是从C语言借鉴的分支结构 if/else分支结构ifBoolean{state__nets;}else{statements;} switch分支结构switchexpr1{caseexpr2:statements;break;caseexpr3:statements;break;default:statements;break;} 循环结构for循环结构forinitexpr1;testexpr2;incrementexpr3{statements;} While循环结构WhileBoolean{statements;} Do循环结构do{statements;}whileBoolean; 一般顺序控制break[label]continue[label]reutrnexpr;label:statement; for循环例子下面是一个程序例子,画几条线,分别用红绿蓝颜色,这段程序可能是J__a函数的一部分intcount;forcount=1;count=12;count++{switchcount%3}case0:setColorColor.red;break;case1:setColorColor.blue;break;case2:setColorColor.green;break;}g.drawLine10count*1080count*10;}
3.2J__a变量和函数的实例 J__a的类包含变量和函数数据变量可以是一些原始的类型如intchar等成员函数是一些可执行的过程例如下面程序里publicclassClassOne{inti;publicClassOne{i=10;}publicvoidAdd_iintj{i=i+j;}}ClassOne包含一个变量i和两个成员函数ClassOneintfirst和Add_iintj 成员函数成员函数是一些可被其它类或自己类调用的处理子程序一个特殊的成员函数叫构造函数这个函数名称一般与本类名程相同它没有返回值构造函数和成员函数当你在J__a里定义一个类时你可定义一个或多个可选的构造函数当创建本类的一个对象时用某一个构造函数来初始化本对象用前面的程序例子来说明当ClassOne类创建一个新实例时所有成员函数和变量被创建创建实例构造函数被调用ClassOnemc:mc=newClassOne; 关键词new用来创建一个类的实例一个类用new初始化前并不占用内存它只是一个类型定义当mc对象初始化后mc对象里的i变量等于10你可以通过对象名来引用变量i有时称为实例变量mc.i++;//mc实例变量加1因为mc有ClassOne类的所有变量和成员函数,我们可以使用同样的语法来调用成员函数Add_i Add_i10;现在mc.i变量等于
21. 结束函数J__a并不支持析构函数C++里的定义因为j__a本身提供对象无用时自动清除的功能同时它也提供了一个自动拉圾箱的成员函数,在清除对象时被调用Protectedvoidfinalize{close;}
3.3对象有效范围和废物自动回收对象有一定的生命期并在它的生命期间使用资源当一个对象不再被使用时它应释放内存避免内存溢出在J__a里收集和释放内存是一个叫自动废品回收站的线程的责任这个线程监视对象有效范围并给一个走出有效范围的对象作上标识 例如Strings;//没有分配内存s=newString\oldstring\;//分配内存s=\newstring\;//重新分配内存创建新对象我们将在以后访问String类时将更加明白它的工作过程但它的快速工作过程是这样的
1.创建一个新的String类对象并填充以\oldstring\
2.创建另一个String对象并填充以\newstring\注意我们创建了两个对象Stirng对象\oldstring\Stirng对象\newstring\在第三条语句里第一个包括\oldstring\的叫做s的对象已走出了有效范围没有任何方法可以再访问他我们现在有一个新的对象也叫s包含\newstring\在下一个废品回收线程前一个对象将被标识并清除
3.4子类 子类是利用存在的对象创建一个新对象的机制比如如果你有一个Horse类你可以创建一个Zebra子类Zebra是Horse的一种 classZebraextendsHorse{intnumber_OF_stripes:}关键词extends来定义对象有的子类.Zebra是Horse的子类Horse类里的所有特征都将拷贝到Zebra类里而Zebra类里可以定义自己的成员函数和实例变量Zebra称为Horse的派生类或继承另外你也许还想覆盖基类的成员函数用ClassOne说明下面是一个派生类覆盖Add_i功能的例子.importClassOne;publicclassNewClassextendsClassOne{publicvoidAdd_iintj{i=i+j/2;}} 当NewClass类的实例创建时变量i初始化值为10但调用Add_i产生不同的结果NewClassmnc;mnc=newNewClass;mnc.Add_i10;访问控制J__a里当你创建一个新类时你可以标明变量和成员函数的访问层次 publicpublicvoidAnyOneCanAc__ss{}public实例变量和成员函数可以任意其它类调用 protectedprotectedvoidOnlySubClasses{}protected实例变量和成员函数只能被其子类调用. privateprivateStringCreditCardNumber;private实例变量和成员函数只能在本类里调用. friendlyvoidMyPackageMethod{}缺省的如果没有定义任何防火控制实例变量或函数缺省定义成friendly意味着可以被本包里的任意对象防问但其它包里的对象不可防问静态成员函数和变量有copy;时候你创建一个类希望这个类的所有实例都公用一个变量也就是说所有这个类的对象都只有实例变量的同一个拷贝这种方法的关键词是static,例如classBlock{ staticintnumber=50;} 所有从Block类创建的对象的number变量值都是相同的无任在哪个对象里改变了number的值所有对象的number都跟着改变同样的你可以定义static成员函数但这个成员函数不能访问非static函数和变量classBlock{staticintnumber=50;intlocalvalue;staticvoidadd_local{localvalue++;//没有运行}staticvoidadd_static{number++;//运行}}
3.5this和super 访问一个类的实例变量时this关键词是指向这个类本身的指针在前面ClassOne例子中我们可以增加构造函数如下 publicclassClassOne{inti;publicClassOne{i=10;} publicClassOneintvaluethis.i=value;} publicvoidAdd_iintj{i=i+j;}} 这里this指向ClassOne类的指针如果在一个子类里覆盖了父类的某个成员函数但又想调用父类的成员函数你可以用super关键词指向父类的成员函数importClassOne;publicclassNewClassextendsClassOne{publicvoidAdd_iintj{i=i+j/2;super.Add_ij;}} 下面程序里i变量被构造函数设成10然后15,最后被父类ClassOne设成25NewClassmnc;mnc=newNewClass;mnc.Add_i10;
3.6类的类型 至今为止我用在类前面只用了一个public关键词其实它有下面4种选择abstract一个abstract类必须至少有一个虚拟函数一个abstract类不能直接创建对象必须继承子类后才能 final一个final类声明了子类链的结尾用final声明的类不能再派生子类publicpublic类能被其它的类访问在其它包里如果想使用这个类必须先import则它只能在它定义的package里使用synchronicable这个类标识表示所有copy;类的成员函数都是同步的
3.7抽象类 面向对象的一个最大优点就是能够定义怎样使用这个类而不必真正定义好成员函数如果程序由不同的用户实现时是很有用的,这不需用户使用相同的成员函数名 在j__a里Graphics类里一个abstract类的例子如下publicabstractclassGraphics{publicabstractvoiddrawLineintx1inty1intx2inty2;publicabstractvoiddrawOvalintxintyintwidthintheight;publicabstractvoiddrawRectintxintyintwidthintheight;...} 在Graphics类里声明了几个成员函数但成员函数的实际代码是在另外一copy;地方实现的 publicclassMyClassextendsGraphics{publicvoiddrawLineintx1inty1intx2inty2{画线程序代码}} 当一个类包含一个abstract成员函数这个类必须定义为abstract类然而并不是abstract类的所有的成员函数都是abstract的Abstract类不能有私有成员函数它们不能被实现也不能有静态成员函数
3.8接口 当你确定多个类的操作方式都很相象时,abstract成员函数是很有用的但如果你需要使用这copy;abstract成员函数,必须创建一个新类,这样有时很繁琐接口提copy;了一种抽象成员函数的有利方法一个接口包含了在另一个地方实现的成员函数的收集成员函数在接口里定义为public和abstract接口里的实例变量是publicstatic和final接口和抽象的主要区别是一个接口提copy;了封装成员函数协议的方法而不必强迫用户继承类例子publicinte_____AudiClip{//Startplayingtheclip.voidplay;//Playtheclipinaloop.voidloop;//Stopplayingtheclipvoidstop;} 想使用AudioClip接口的类使用implenents关键词来提copy;成员函数的程序代码classMyClassimplementsAudioClip{voidplay{实现代码}voidloop实现代码}voidstop实现代码}} 优点一个接口类可以被任意多的类实现,每个类可以共享程序接口而不必关心其它类是怎样实现的classMyOtherClassimplementsAudioClip{voidstop{实现代码}...}内部成员函数J__a还提copy;了调用C和C++函数的方法用native关键词来定义C和C++的函数publicclassDate{intnow;publicDate{now=time;}privatenativeinttime;static{System.loadLibrary\time\;}}一copy;J__a代码写好后就需要以下步骤执行
1.用j__ah来创建头文件.h
2.用j__ah来创建stub文件
3.用C和C++写native成员函数的代码
4.编译stub文件和.C文件成一个动态可加载库
5.用j__a运行j__a程序或appletviewer运行applet注意Native成员函数超出了类的范围
3.9包Packages 包Package由一组类class和界面inte_____组成它是管理大型名字空间,避免名字冲突的工具每一个类和界面的名字都包含在某个包中按照一般的习惯,它的名字是由\.\号分隔的单词构成,第一个单词通常是开发这个包的组织的名称 如果j__a源文件不包含package它放在缺省的无名package这与源文件同目录,类可以这样引入:importMyClass J__a系统包J__a语言提copy;了一个包含窗口工具箱,实用程序,一般I/O工具和网络功能的包 j__a.applet这个包包含量了一copy;设计applet的类用一个类Applet和三个接口.AppletContext;AppletStub;和AudioClip. j__a.awt另一个窗口工具箱包.awt包含了一copy;产生装饰物和GUI成员的类这个package包括 ButtonCheckboxChoi__ComponentGraphicsMenuPane1TextArea和TextField j__a.ioI/Opackage包含文件输入/输出类,FileInputStream和FileOutputStream. j__a.lang这个包包含J__a语言类包含:对象线程异常出口系统整数原点数学字符等 j__a.net这个类支持TCP/IP网络协议,并包含Socket类URL和URL相联系的类 j__a.util这个类包含一copy;程序的同步类它包含DateDictionary类等
3.10异常 当在J__a程序中发生一个错误时,例如一个变元的值非法,代码会发现这个错误,并引发一个异常ex__ption在缺省的情况下,异常会输出一个错误消息,然后中止线程的执行但是,程序自己可以定义异常处理段ex__ptionhandler来截获catch异常,并从错误中恢复有一copy;异常是由J__a解释器在运行时刻引发的实际上,任何类都可以定义属于自己的异常,并使用throw语句引发它们一个throw(引发copy;语句是由throw关键字和一个对象构成按常规,该对象应该是Ex__ption类的实例或其子类的实例throw语句会引起执行转向相应的异常处理段当一个throw语句执行时,它下面的所有代码不再执行了,它所在的方法也不再返回值下面的例子将演示如何创建一个Ex__ption的子类,然后引发一个异常classMyEx__ptionextendsEx__ption{}classMyClass{voidoops{if/*不出现错误*/{…}else{/*出错*/}else{/*出错*/thrownewMyEx__ption;}}}为了定义一个异常处理段,程序必须用try语句把可能产生异常的代码成组在try语句后面跟上一个或多个catch截获copy;语句,每个异常对应一个catch语句每个catch语句中包含着异常处理段例如try{p.a=10;}catchNullPointerEx__ptione{println\pwasnull\;}catchEx__ptione{println\othererrorsoccured\;}catchO__ecto__{println\Whothrewthato__ect\;}catch语句和一个方法定义类似,只不过该方法只有一个参数,且无返回类型参数可以是一个类或一个界面当一个异常发生时,嵌套的try/catch语句会寻找出与该异常类相匹配的参数如果一个参数和指定异常匹配则*该参数和指定的异常是同一个类,或*该参数是指定异常的子类,或*如果参数是一个界面,指定异常类实现了这个界面第一个参数和异常匹配的try/catch语句,则与其匹配的catch语句执行在catch语句执行完后,程序的执行被恢复但已不可能恢复到异常发生处再次执行例如print\now\;try{print\is\;thrownewMyEx__ption;print\a\;}catchMyEx__ptione{print\the\;}print\time\\n\;打印为\nowisthetime\正如这个例子所示,异常应该主要用于错误处理,若用于其它方面会使代码晦涩难reg;异常处理段是可以嵌套的,允许异常处理可以发生在多个地方嵌套异常处理通常用于当第一个处理程序无法完全从错误中恢复过来的时候,而不得不执行一copy;清除代码为了把异常处理控制传递给更高层的处理段,可以再一次对截获对象实copy;throw操作注要再次实throw异常的方法,throw语句执行完后,会终止执行try{f.open;}catchEx__ptione{f.close;throwe;}定局语句finally(定局copy;语句是用于保证无论在异常是否发生的情况下,某copy;代码被执行下例说明finally语句的用法try{//做某copy;动作;}finally{//此后清除;}和以下代码类似try{//做某copy;动作}catchO__ecte{//此后清除;throwe;}}//此后清除;即使try块中包含return,break,continue,throw语句,finally语句也会被执行例如下面的代码\finally\总是被输出,而\aftertry\仅在a!=10时被输出try{ifa==10{return;}}finally{print\finally\\n\;}print\aftertry\\n\;运行时刻异常本节列出的清单是J__a解释器引发的各种异常当运行时刻发现各种错误,由解释器引发异常Arithmeti__x__ption如果程序试图除0,或用0取模,会产生Arithmeti__x__ption(算术异常copy;,其它算术操作不会产生异常有关J__a如何处理其它算术错误的信息,见\整数运算符\和\浮点运算符\两节例如下面的代码将会引发Arithmeti__x__ption异常classArith{publicstaticvoid__inStringargs[]{intj=0;j=j/j;}}NullPointerEx__ption当程序试图访问一个空对象中的变量或方法,或一个空数组中的元素时则引发NullPointerEx__ption(空指针异常copy;例如,访问长度为0的数组a
[0]有以下类声明,运行时会引发NullPointerEx__ption异常classNull{publicstaticvoid__inStringargs[]{Stringo=null;inta[]=null;o.length;a
[0]=0;}}有趣的是,如果我们引发一个空对象,也会产一NullPointerEx__ption异常IncompatibleClassChangeEx__ption当一个类的定义被改变,而引用该类的其它类没有被重新编译时,会产生这一异常有四种类更改会导致运行时刻引发IncompatibleClassChangEx__ption异常*一个类中的变量声明由static变成非static,而其它访问该类这一变量的类没有被重新编译*一个类中的变量声明由非static变成static,而其它访问该类这一变量的类没有被重新编译*类中声明的某个域被删除,而其它访问该域的类没有被重新编译*类中声明的某个方法被删除,而其它访问该方法的类没有被重新编译 ClassCastEx__ption如果试图把对象o强制成ClassC,而o既不是ClassC的实例,也不是ClassC子类的实例,这时便会产生ClassCastEx__ptionclassClassCast{publicstaticvoid__inStringargs[]{O__ecto=newO__ect;Strings=stringo;s.length;}}}NagativeArraySizeEx__ption如果一个数组的长度是负数,则会引发NagativeArraySizeEx__ption(数组负下标copy;异常例如下面类定义的代码在运行时引发这一异常classNegArray{publicstaticvoid__inStringargs[]{inta[]=newint[-1];a
[0]=0;}} OutOfMemoryEx__ption当系统无法再向应用程序提copy;内存时,会引发OutOfMemoryEx__ption(内存溢出copy;异常这种异常只能出现在创建新对象的时候,即new被调用的时候例如,下面一段代码在运行时刻会引发OutOfMemoryEx__ption异常classLink{inta[]=newint[_____00];Linkl;}ClassOutOfMem{publicstaticvoid__inStringargs[]{publicstaticvoid__inStringargs[]{Linkroot=newlink;Linkcur=root;whiletrue{cur.l=newLink;cur=cur.l;}}}NoClassDefFoundEx__ption如果一个类被引用,但在运行时刻,系统没有找到被引用的类,这时会引发NoClassDefFoundEx__ption(未找到类定义copy;异常例如,NoClass的声明如下classNoClass{publicstaticvoid__inStringargs[]{Cc=newC;}}当NoClass运行时,如果解释器找不到C类,则会产生NoClassDefFoundEx__ption注意,在NoClass被编译时C类一定要存在 IncompatibleTypeEx__ption如果试图为一界面作实例,则会引发IncompatibleTypeEx__ption(类型不兼容copy;异常例如,下面的代码会引发一个IncompatibleTypeEx__ptionInte_____I{}classIncompType{publicstaticvoid__inStringargs[]{Ir=Inew\I\;}}ArrayIndexOutOfBound_____ption试图访问数组中的一个非法元素时,会引发ArrayIndexOutOfBound_____ption(数组索引越界copy;异常例如ClassArrayOut{publicstaticvoid__inStringargs[]{inta[]=newint
[0];a
[0]=0;}}publicstaticvoid__inStringargs[]{inta[]=newint
[0];a
[0]=0;}}UnsatisfiedLinkEx__ption如果一个方法被声明为本机,但该方法在运行时刻却不能连接到一个例程体上去时,会产生UnsatisfiedLinkEx__ption(无法连接copy;异常例如ClassNoLink{staticnativevoidfoo;publicstaticvoid__inStringargs[]{foo;}}InternalEx__ptionInternalEx__ption(内部copy;异常是不能被引发的只有在运行失败作一致性检查时,才会引发这个异常本章小结
1.J__a语言的基本结构象C/C++
2.J__a语言的源程序代码由一个或多个编译单元compilationunit组成。