按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
访问一个类的实例变量时;this关键词是指向这个类本身的指针;在前面ClassOne例子中;我们可以增加构造函数如下:
publicclassClassOne{inti;publicClassOne(){i=10;}
publicClassOne(intvalue)this。i=value;}
publicvoidAdd_i(intj){i=i+j;}}
这里;this指向ClassOne类的指针。如果在一个子类里覆盖了父类的某个成员函数;但又想调用父类的成员函数;你可以用super关键词指向父类的成员函数。
importClassOne;publicclassNewClassextendsClassOne{publicvoidAdd_i(intj){i=i+(j/2);super。Add_i(j);}}
下面程序里;i变量被构造函数设成10;然后15,最后被父类(ClassOne)设成25。NewClassmnc;mnc=newNewClass();mnc。Add_i(10);
3。6类的类型
至今为止;我用在类前面只用了一个public关键词;其实它有下面4种选择:abstract一个abstract类必须至少有一个虚拟函数;一个abstract类不能直接创建对象;必须继承子类后才能。
final一个final类声明了子类链的结尾;用final声明的类不能再派生子类。publicpublic类能被其它的类访问。在其它包里;如果想使用这个类必须先import;则它只能在它定义的package里使用。synchronicable这个类标识表示所有?copy;类的成员函数都是同步的。
3。7抽象类
面向对象的一个最大优点就是能够定义怎样使用这个类而不必真正定义好成员函数。如果程序由不同的用户实现时是很有用的,这不需用户使用相同的成员函数名。
在java里Graphics类里一个abstract类的例子如下:publicabstractclassGraphics{publicabstractvoiddrawLine(intx1;inty1;intx2;inty2);publicabstractvoiddrawOval(intx;inty;intwidth;intheight);publicabstractvoiddrawRect(intx;inty;intwidth;intheight);。。。}
在Graphics类里声明了几个成员函数;但成员函数的实际代码是在另外一?copy;地方实现的。
publicclassMyClassextendsGraphics{publicvoiddrawLine(intx1;inty1;intx2;inty2){}}
当一个类包含一个abstract成员函数;这个类必须定义为abstract类。然而并不是abstract类的所有的成员函数都是abstract的。Abstract类不能有私有成员函数(它们不能被实现);也不能有静态成员函数。
3。8接口
当你确定多个类的操作方式都很相象时,abstract成员函数是很有用的。但如果你需要使用这?copy;abstract成员函数,必须创建一个新类,这样有时很繁琐。接口提?copy;了一种抽象成员函数的有利方法。一个接口包含了在另一个地方实现的成员函数的收集。成员函数在接口里定义为public和abstract。接口里的实例变量是public;static和final。接口和抽象的主要区别是一个接口提?copy;了封装成员函数协议的方法而不必强迫用户继承类。例子:publicinterfaceAudiClip{//Startplayingtheclip。voidplay();//Playtheclipinaloop。voidloop();//Stopplayingtheclipvoidstop();}
想使用AudioClip接口的类使用implenents关键词来提?copy;成员函数的程序代码。classMyClassimplementsAudioClip{voidplay(){}voidloop}voidstop}}
优点一个接口类可以被任意多的类实现,每个类可以共享程序接口而不必关心其它类是怎样实现的。classMyOtherClassimplementsAudioClip{voidstop(){}。。。}内部成员函数Java还提?copy;了调用C和C++函数的方法。用native关键词来定义C和C++的函数。publicclassDate{intnow;publicDate(){now=time();}privatenativeinttime();static{System。loadLibrary(”time”);}}一?copy;Java代码写好后;就需要以下步骤执行:1。用javah来创建头文件(。h)2。用javah来创建stub文件3。用C和C++写native成员函数的代码4。编译stub文件和。C文件成一个动态可加载库5。用java运行java程序或appletviewer运行applet注意:Native成员函数超出了类的范围。
3。9包(Packages)
包(Package)由一组类(class)和界面(interface)组成。它是管理大型名字空间,避免名字冲突的工具。每一个类和界面的名字都包含在某个包中。按照一般的习惯,它的名字是由”。”号分隔的单词构成,第一个单词通常是开发这个包的组织的名称。
定义一个编译单元的包编译单元的包由package语句定义。如果使用package语句,编译单元的第一行必须无空格,也无注释。其格式如下:packagepackageName;若编译单元无package语句,则该单元被置于一个缺省的无名的包中。使用其它包中的类和界面在Java语言里提?copy;一个包可以使用另一个包中类和界面的定义和实现的机制。用import关键词来标明来自其它包中的类。一个编译单元可以自动把指定的类和界面输入到它自己的包中。在一个包中的代码可以有两种方式来定义来自其它包中的类和界面:*在每个引用的类和界面前面给出它们所在的包的名字;//前缀包名法acme。project。FooBarobj=newacme。project。FooBar();*使用import语句,引入一个类或一个界面,或包含它们的包。引入的类和界面的名字在当前的名字空间可用。引入一个包时,则该包所有的公有类和界面均可用。其形式如下://从acme。project引入所有类importacme。project。*;这个语句表示acme。project中所有的公有类被引入当前包。以下语句从acme。project包中进入一个类Employec_List。//从acme。project而引入Employee_Listimportacme。project。Employee_list;Employee_Listobj=newEmployee_List();在使用一个外部类或界面时,必须要声明该类或界面所在的包,否则会产生编译错误。import(引用)类包(classpackage)用import关键词调入;指定package名字如路径和类名;用*匹配符可以调入多于一个类名。
importjava。Date;importjava。awt。*;
如果java源文件不包含package;它放在缺省的无名package。这与源文件同目录,类可以这样引入:importMyClass。
Java系统包:Java语言提?copy;了一个包含窗口工具箱,实用程序,一般I/O;工具和网络功能的包。
java。applet这个包包含量了一?copy;设计applet的类;用一个类Applet和三个接口。AppletContext;AppletStub;和AudioClip。
java。awt另一个窗口工具箱包。awt;包含了一?copy;产生装饰物和GUI成员的类。这个package包括:
Button;Checkbox;Choice;ponent;Graphics;Menu;Pane1;TextArea和TextField。
java。ioI/Opackage包含文件输入/输出类,FileInputStream和FileOutputStream。
java。lang这个包包含Java语言类;包含:对象;线程;异常出口;系统;整数;原点;数学;字符等。
java这个类支持TCP/IP网络协议,并包含Socket类;URL和URL相联系的类。
java。util这个类包含一?copy;程序的同步类;它包含Date;Dictionary类等。
3。10异常
当在Java程序中发生一个错误时,例如:一个变元的值非法,代码会发现这个错误,并引发一个异常(exception)。在缺省的情况下,异常会输出一个错误消息,然后中止线程的执行。但是,程序自己可以定义异常处理段(exceptionhandler)来截获(catch)异常,并从错误中恢复。有一?copy;异常是由Java解释器在运行时刻引发的。实际上,任何类都可以定义属于自己的异常,并使用throw语句引发它们。一个throw(引发?copy;语句是由throw关键字和一个对象构成。按常规,该对象应该是Exception类的实例或其子类的实例。throw语句会引起执行转向相应的异常处理段。当一个throw语句执行时,它下面的所有代码不再执行了,它所在的方法也不再返回值。下面的例子将演示如何创建一个Exception的子类,然后引发一个异常。classMyExceptionextendsException{}classMyClass{voidoops(){if(/*不出现错误*/){…}else{/*出错*/}else{/*出错*/thrownewMyException();}}}为了定义一个异常处理段,程序必须用try语句把可能产生异常的代码成组。在try语句后面跟上一个或多个catch(截获?copy;语句,每个异常对应一个catch语句。每个catch语句中包含着异常处理段。例如:try{p。a=10;}catch(NullPointerExceptione){println(”pwasnull”);}catch(Exceptione){println(”othererrorsoccured”);}catch(Objectobj){println(”Whothrewthatobject?”);}catch语句和一个方法定义类似,只不过该方法只有一个参数,且无返回类型。参数可以是一个类或一个界面。当一个异常发生时,嵌套的try/catch语句会寻找出与该异常类相匹配的参数。如果一个参数和指定异常匹配则:*该参数和指定的异常是同一个类,或*该参数是指定异常的子类,或*如果参数是一个界面,指定异常类实现了这个界面。第一个参数和异常匹配的try/catch语句,则与其匹配的catch语句执行。在catch语句执行完后,程序的执行被恢复。但已不可能恢复到异常发生处再次执行。例如:print(”now”);try{print(”is”);thrownewMyException();print(”a”);}catch(MyExceptione){print(”the”);}print(”timen”);打印为”nowisthetime”。正如这个例子所示,异常应该主要用于错误处理,若用于其它方面会使代码晦涩难?reg;。异常处理段是可以嵌套的,允许异常处理可以发生在多个地方。嵌套异常处理通常用于当第一个处理程序无法完全从错误中恢复过来的时候,而不得不执行一?copy;清除代码。为了把异常处理控制传递给更高层的处理段,可以再一次对截获对象实?copy;throw操作。注要再次实throw异常的方法,throw语句执行完后,会终止执行。try{f。open();}catch(Exceptione){f。close();throwe;}定局语句finally(定局?copy;语句是用于保证无论在异常是否发生的情况下,某?copy;代码被执行。下例说明finally语句的用法:try{//做某?copy;动作;}finally{//此后清除;}和以下代码类似try{//做某?copy;动作}catch(Objecte){//此后清除;throwe;}}//此后清除;即使try块中包含return,break,continue,throw语句,finally语句也会被执行。例如:下面的代码”finally”总是被输出,而”aftertry”仅在a!=10时被输出。try{if(a==10){return;}}finally{print(”finallyn”);}print(”aftertryn”);运行时刻异常本节列出的清单是Java解释器引发的各种异常。当运行时刻发现各种错误,由解释器引发异常。ArithmeticException如果程序试图除0,或用0取模,会产生ArithmeticException(算术异常?copy;,其它算术操作不会产生异常。有关Java如何处理其它算术错误的信息,见”整数运算符”和”浮点运算符”两节。例如:下面的代码将会引发ArithmeticException异常:classArith{publicstaticvoidmain(Stringargs''){intj=0;j=j/j;}}NullPointerException当程序试图访问一个空对象中的变量或方法,或一个空数组中的元素时则引发NullPointerException(空指针异常?copy;。例如,访问长度为0的数组a'0'。有以下类声明,运行时会引发NullPointerException异常:classNull{publicstaticvoidmain(Stringargs''){Stringo=null;inta''=null;o。length();a'0'=0;}}有趣的是,如果我们引发一个空对象,也会产一NullPointerException异常。InpatibleClassChangeException当一个类的定义被改变,而引用该类的其它类没有被重新编译时,会产生这一异常。有四种类更改会导致运行时刻引发InpatibleClassChangException异常。*一个类中的变量声明由static变成非static,而其它访问该类这一变量的类没有被重新编译。*一个类中的变量声明由非static变成static,而其它访问该类这一变量的类没有被重新编译。*类中声明的某个域被删除,而其它访问该域的类没有被重新编译。*类中声明的某个方法被删除,而其它访问该方法的类没有被重新编译。
ClassCastException如果试图把对象o强制成ClassC,而o既不是ClassC的实例,也不是ClassC子类的实例,这时便会产生ClassCastException。classClassCast{publicstaticvoidmain(Stringargs''){Objecto=newObject();Strings=(string)o;s。length();}}}NagativeArraySizeException如果一个数组的长度是负数,则会引发NagativeArraySizeException(数组负下标?copy;异常。例如下面类定义的代码在运行时引发这一异常:classNegArray{publicstaticvoidmain(Stringargs''){inta''=newint'…1';a'0'=0;}}
OutOfMemoryException当系统无法再向应用程序提?copy;内存时,会引发OutOfMemoryException(内存溢出?copy;异常。这种异常只能出现在创建新对象的时候,即new被调用的时候。例如,下面一段代码在运行时刻会引发OutOfMemoryException异常:classLink{inta''=newint'1000000';Linkl;}ClassOutOfMem
{publicstaticvoidmain(Stringargs''){publicstaticvoidmain(Stringargs''){Linkroot=newlink();Linkcur=root;while(true){cur。l=newLink();cur=cur。l;}}}NoClassDefFoundException如果一个类被引用,但在运行时刻,系统没有找到被引用的类,这时会引发NoClassDefFoundException(未找到类定义?copy;异常。例如,NoClass
的声明如下:classNoClass{publicstaticvoidmain(Stringargs''){Cc=newC();}}当NoClass运行时,如果解释器找不到C类,则会产生NoClassDefFoundException。注意,在NoClass被编译时C类一定要存在。
InpatibleTypeException如果试图为一界面作实例,则会引发InpatibleTypeException(类型不兼容?copy;异常。例如,下面的代码会引发一个InpatibleTypeException。InterfaceI{}classInpType{publicstaticvoidmain(Stringargs''){Ir=(I)new(”I”);}}ArrayIndexOutOfBoundsException试图访问数组中的一个非法元素时,会引发ArrayIndexOutOfBoundsException(数组索引越界?copy;异常。例如:ClassArrayOut{publicstaticvoidmain(Stringargs''){inta''=newint'0';a'0'=0;}}publicstaticvoidmain(Stringargs''){inta''=newint'0';a'0'=0;}}UnsatisfiedLinkException如果一个方法被声明为本机,但该方法在运行时刻却不能连接到一个例程体上去时,会产生UnsatisfiedLinkException(无法连接?copy;异常。例如:ClassNoLink{staticnativevoidfoo();publicstaticvoidmain(Stringargs''){foo();}}InternalExceptionInternalException(内部?copy;异常是不能被引发的。只有在运行失败作一致性检查时,才会引发这个异常。
本章小结
1。Java语言的基本结构象C/C++。2。Java语言的源程序代码由一个或多个编译单元(pilationunit)组成。
第四章Java应用程序的基本框架
学习一门新语言最好是先看几个简单的程序例子。下面我们将看到几个非常基本的程序例子。
4。1Java应用程序的运行环境
Java应用程序是指可以独立运行在Java虚拟机上的程序,它是一种中间代码(byte…code?copy;。比如你的应用程序叫my。java,程序里有一个名称为app1的类,用Javac或其它编译器,编译后将会生成app1。class,则在命令行状态下输入:javaapp1就可以运行此程序。注意,用java命令运行的类必须有main函数,否则不能执行。与普通java应用程序不同的另一种另一种Java程序叫JavaApplet。我们把它译成Java小程序,这种程序后缀也是。class,但它不能直接在java虚拟机上运行,也就是输入java*。class不能运行,这种程序里可以没有main函数,它必须由某个浏览器来运行,比如Appletviewer或Netscape2。02以上等。这种程序我们将在后面章节中介绍。
4。2最简单的Java程序解释
让我们来看一看最简单的Java应用程序例子,来理解一下它的结构:Filename:1。javaclassmyfirst{publicstaticvoidmain(Stringargs''){System。out;println(”ThisismyfirstJavaApplication”);}}这就是一个完整的Java应用程序,将它编译:Javac1。java在当前目录下,它将生成myfirst。class文件,Javamyfirst屏幕上将会输出:ThisismyfirstJavaApplication让我们来一步一步分析每句话含义(1?copy;classmyfirst这一行用关键词class来定义名为myfirst的新类,myfirst是新类的名称,必须是一个有效的标识符,有效标识符定义请见程序设计基础章节。类的说明包括数据说明和成员函数说明,都放在类后面的大括号里面。一般类定义如下:class类名称{数据定义;函数定义;}
(2)publicstaticvoidmain(Stringargs'')public是一个表示访问权限的关键字,表示此成员函数是公有的,可以被其他类直接调用,包括java解释器。相对应的关键字有private和protected,friend。private表示只能被本类访问,protected表示只能被子类访问,friend是缺省的访问权限,表示能被本包(package)中任意类访问,对其它包中的类是不可访问的。
static表示main成员函数在myfirst类的所有对象中是唯一的,因此如果本程序生成另一个myfirst类对象,调用的main函数将是同一个函数。void表示main函数没有返回值,如果有返回类型值,则可加上interger或boolean诸如此类,对于有返回值的函数,其函数实体的最后应加上return语句。main这个函数是这运行应用程序的入口点,因此编写应用程序是必须有main()函数,且是唯