2.13k likes | 2.5k Views
JAVA 网络编程基础. 第一部分 JAVA 程序设计基础. 第五 章 异常处理 第六 章 Java 的可重用类. 第一 章 计算机语言概述. 第一节 程序设计语言 第二节 语言翻译程序 第三节 Java 虚拟机与运行环境 第四节 Java 程序的运行 第五节 Java 程序的开发、执行流程 小结 习题. 第二章 Java 的开发环境. 第一节 Java 的开发环境 第二节 JDK 的安装、环境配置及使用 第三节 JBuilder 6 的开发环境 小结 习题.
E N D
JAVA 网络编程基础
第一部分JAVA程序设计基础 • 第五章 异常处理 • 第六章 Java的可重用类
第一章计算机语言概述 • 第一节 程序设计语言 • 第二节 语言翻译程序 • 第三节 Java虚拟机与运行环境 • 第四节 Java程序的运行 • 第五节 Java程序的开发、执行流程 • 小结 • 习题
第二章 Java的开发环境 • 第一节 Java的开发环境 • 第二节 JDK的安装、环境配置及使用 • 第三节 JBuilder 6的开发环境 • 小结 • 习题
第三章 Java语言基础 • 第一节 一个简单的Java程序实例 • 第二节 标识符、注释和分隔符 • 第三节 变量和常量 • 第四节 基本类型 • 第五节 运算符及表达式 第六节 运算符的优先级 第七节 数据类型转换 第八节 语句和复合语句 小结 习题
第四章 Java面向对象的程序设计 • 第一节 面向对象的理论基础 • 第二节 类与对象的基本概念 • 第三节 Java的类 • 第四节 继承 • 第五节 对象的创建及使用 第六节 null , this 和 super 第七节 接口 第八节 包 小结 习题
第五章 • 5.1 异常类的层次 • 5.2 throws抛出异常 • 5.3 throw抛出异常 • 5.4 try-catch异常处理 5.5Finally子句 5.6 正确地使用异常 小结 习题
第五章 异常处理 • 一 为什么要引入异常 • 二 异常的几个概念(处理机制) • 三 异常处理 • 四 小结
为什么要引入异常机制 • 当程序运行的时候,经常会由于各种不可避免的原因而产生错误。 一个好的程序应该可以自己处理这些错误,而不是使整个程序全部瘫痪 。 • Java把运行中各种可能出现的错误都看作异常并提供了异常处理的能力(异常处理)。
异常的几个概念 • 异常机制的过程:抛出异常——捕捉异常 1 当出现了一些错误,方法都会产生一个异常对象,这个异常对象将交由运行系统来处理。此过程就称为抛出(throwing)异常。 2 接着,运行系统开始寻找合适的处理方法,来处理这个异常。如果系统找到了一个适合的处理该异常方法,这一过程就叫捕获异常。 包括:系统抛出 用户自定义抛出
Object Throwable Exception Error IOException RuntimeException Non-RuntimeException Object 异常类的结构
异常类常用的方法 public Exception() public Exception(String s):该参数一般表示该异常对应的错误的描述 public String toString(): 返回描述当前异常对象信息的字符串 。 public String getMessage():返回描述当前异常对象信息的详细信息。 public void printStackTrace():打印当前异常对象使用堆栈的轨迹。
异常处理机制的语法支持 • 异常处理由try/catch/[finally]三个语句组成的: ⑴ try包含可能出现异常的语句块 ⑵ 一个或多个catch块紧随try{}块,每个catch块通常处理指定类型的异常 ⑶finally引导块紧随catch块后,主要用于清理现场(可有可无) 注意:finally块总是执行,catch块不一定执行 格式: try {...... }catch( ExceptionName1 e ) { ......} catch( ExceptionName2 e ) {......} finally {......}
自定义的抛出异常 自定义抛出语句throw 异常类对象; 说明: ⑴throw之后必须接异常类(Throwable或其子类)的实例。 ⑵ 程序会在throw语句立即终止,其后的语句不再执行 ⑶ 抛出语句应在满足一定条件时执行(如与if连用) ⑷含有throw语句的方法,抛出的异常一般由调用者处理
声明可能生成但没处理的异常 • 指定函数抛出的异常 方法内的代码有可能发生异常而又不自己进行处理时,就必须在声明方法时一并指出方法有可能发生的异常,以便该方法的调用者或系统的预设处理方法能够捕获并处理由方法抛出的异常。 • 声明格式: 返回类型 方法名([参数列表]) throws 异常类列表 { <方法体>} • 注意: Error和RuntimeException类及它们的子类一般不需在方法声明中指定(属Java不检查异常)
小结 • 异常处理把错误集中起来统一处理。程序员只需要说明何处可能出现异常,如何处理即可。
throws抛出异常和方法说明联系在一起,是针对以下况:throws抛出异常和方法说明联系在一起,是针对以下况: • 调用的方法抛出了异常、检测到了错误并使用throw语句抛出异常、程序代码有错误从而异常。 • 方法中出现的异常由catch语句捕获,进行处理。
try-catch异常处理机制。 当try体中发生了一个异常,try-catch语句就会自动在try体后面的各个catch语句中,找出与该异常类相匹配的参数,就执行包含这一参数的catch语句中的Java代码。 • 不论try块中是否发生了异常,是否执行过catch语句,都要执行finally语句,可以说是为异常处理事件提供的一个清理机制。
第六章 Java的可重用类 • 第一节 Java可重用类的结构 • 第二节 Java语言包(Java.lang) • 第三节 常用容器数据类型 • 第四节 输入输出包java.io • 小结 • 习题
5.1 异常类的层次 异常处理的概念 当程序运行的时候,经常会由于各种不可避免的原因而产生错误。例如除数为零、文件找不到而无法读写等等。Java提供的丰富的异常情况处理机制通常叫异常处理。异常处理把Java程序各种可能出现的错误都看作异常,集中起来统一处理。程序员只许要说明何处可能出现异常,如何处理即可。
5.1 异常类的层次 异常在Java中也是作为类的实例的形式出现的。Java中的所有的异常类都是从Throwable类派生出来的。Throwable类有两个直接子类:java.lang.Error和java.lang.Exception。 异常类的层次结构如图5-1所示。 Error类及其子类主要用来描述一些Java运行时刻系统内部的错误或资源枯竭导致的错误。普通的程序不能从这类错误中恢复,也无法抛出这种类型的错误,这类错误出现的几率是很小的。 另一个异常类的子类是Exception类和它的子类。在编程中错误的处理主要是对这类错误的处理,如除数为零、数组下标越界等。类Exception是普通程序可以从中恢复的所有规范了的异常的父类。
5.1 异常类的层次 Exception类又有两个子类:RuntimeException和Non_RuntimeException。 RuntimeException类处理的错误包括:错误的强制类型转换、数组越界访问、空引用。 RuntimeException是程序员编写程序不正确所导致的异常,是在Java系统运行过程中出现的异常,如除数为零等。由于运行时异常可能会出现在程序的任何地方,而且出现的可能性非常大,因而由程序本身去检测运行异常出现与否,将会使程序的开销过大,所以编译器并不要求程序去说明或捕获运行时异常。RuntimeException类的异常的产生是程序员的过失,理论上,程序员经过检查和测试可以查出这类错误。
5.1 异常类的层次 N0_RuntimeException类的异常包括:格式不正确的URL、试图为一个不存在的类找到一个代表它的类的对象。 Non_RuntimeException是指可以由编译器在编译时检测到的、可能会发生在方法执行过程中的异常,如找不到指定名字的类或者界面,不是程序本身的错误,如果这些异常情况没有发生,程序本身仍然是完好的。如果程序不能适当地处理可能会引发运行异常的语句,则程序将不能通过编译器的编译。 Java提供了两种不同的异常抛出机制: throws抛出异常——间接抛出异常 throw 抛出异常——直接抛出异常
图5-1 异常类的层次结构 Object Throwable Exception Error IOException RuntimeException Non-RuntimeException Object
5.2 throws抛出异常 throws异常说明总是和方法说明出现在一起。这样,方法说明告诉编译器该方法可能会产生哪些异常,从而要求它的调用者必须考虑处理这些异常。 带throws异常说明的方法说明形式如下: …方法名(…) [throws 异常类列表] { 方法体 } 方法抛出的异常类是throws子句中指定的异常类或其子类。比如在方法的说明中指明方法可能产生IOException,但是实际上可能抛出的异常或许是EOFException类的实例,这些异常都是IOException的子类。 并不是所有可能发生的异常都要在方法的说明中指定,从Error类中派生出的异常和从RuntimeException类中派生的异常就不用在方法声明中指定。这两类异常属于不检查异常。不检查异常则是那些无法干预的异常。 Java中的另
5.2 throws抛出异常 一类异常是检查异常,检查异常是那些在程序中应该处理的异常,程序完全可以避免的异常(比如数组越界错误)。而throws异常说明必须指定有可能发生的检查异常。 在下列情况下Java方法抛出异常: (1)调用的方法抛出了异常; (2)检测到了错误并使用throw语句抛出异常; (3)程序代码有错误,从而异常,比如数组越界错误。 例5.1 throws抛出一个异常 class Test {…… public String getInput() throws IOException; {……// throws一个异常 } }
5.2 throws抛出异常 例5.2 throws多个异常 class Animation { // throws多个异常 public Image loadImage(String s) throws EOFException, MalformURLException { …… } }
5.3 throw抛出异常 在程序中使用throw语句(注意,这里是throw而不是throws)来抛出异常,该异常可以在该程序中进行捕获、处理,也可以在调用该方法者捕获、处理。 throw语句的形式为: throw 异常类的实例; 例5.3 import java.io.IOException; public class ThrowException { public static voidmain(String args[]) { try { String s=getInput(); //getInput() throw抛出异常 System.out.println(s); }
5.3 throw抛出异常 catch(IOException e)// 捕获异常 {System.out.println(e.getMessage()); } } static String getInput() throws IOException{ // getInput()方法抛出异常,因为在它的方法体中调用的 //read方法抛出异常,并且该方法体本身使用throw抛出异常 char[] buffer =newchar[20]; int counter = 0; boolean flag =true; while(flag) { buffer[counter] =(char)System.in.read();
5.3 throw抛出异常 if(buffer[counter]=='\n') flag = false; counter++; if(counter>=20){ IOException ae =new IOException("buffer is full"); //构造异常实例 throw ae; //抛出异常类的实例 } } return new String(buffer); } }
5.3 throw抛出异常 上面的例中说明了一个方法getInput(),它用来获取从键盘输入的字符,并以字符串对象的形式返回。并且从键盘输入的字符数不能多于20个,否则就抛出一个IOException异常。由于在方法getInput()中,可能会产生IOException异常,所以在方法的说明中必须指明方法可能抛出异常: static String getInput() throws IOException 在方法getInput()中,可能产生异常的地方有两处,一是Java的InputStream类的read()方法。InputStream类的 read()方法如下所示: public abstract int read() throws IOException 但是在方法getInput()中,我们并没有捕获和处理这个异常:buffer[counter]= (char)System.in.read();
5.3 throw抛出异常 另一个可能产生异常的地方是方法中的while循环: while(flag) {buffer[counter] = (char)System.in.read(); if(buffer[counter]= =‘\n’) flag = false; counter++; if(counter>=20) {IOException ae =new IOException(“buffer is full”); throw ae; } }
5.3 throw抛出异常 在这个循环中,如果输入的字符数大于20,就会抛出一个IOException异常(这里只是作为抛出异常的一个示范,实际上这并不是IOException异常)。而在方法main中将捕获这个异常,并打印出异常的信息。如果没有异常发生,就打印输入得到的字符串。 可以看出,抛出异常有这样三步: (1)确定异常类; (2)创建异常类的实例; (3)抛出异常。
5.4 try-catch异常处理 利用try-catch语句可以说明抛出异常的部位,同时又说明捕获、处理的办法。 try…catch语句形式如下: try { 语句系列 } catch(异常类1 变量名1){ catch处理 } …… catch(异常类n 变量名n){ catch处理 } [finally 语句] 其中: try之后的复合语句说明抛出异常的部位,该部位含有抛出异常的语句,如调用抛出异常的方法等; catch(异常类 变量名) 是按抛出的异常类进行捕获; catch处理是对捕获的异常作相应的处理; 如果有finally部分,其后的语句是最后必然要执行的语句。
5.4 try-catch异常处理 例 5.4 try-catch异常处理 : import java.io.*; public class Try_catch {public static voidmain (String args[]) {FileInputStream fis=null; try { fis=new FileInputStream(“c:/filename.txt”); } // FileInputStream 方法抛出异常,所以位于try体内 catch(FileNotFoundException e) //捕获FileNotFoundException异常 {System.out.println("catchexception"+e.getMessage());}
5.4 try-catch异常处理 try { int c=fis.read(); //调用的read()方法抛出异常 } catch(IOException e) //捕获IOException异常 { System.out.println("catchexception:"+e.getMessage()); } } } 上述try-catch语也可改写成:
5.4 try-catch异常处理 try//有多个语句抛出异常 { fis=new FileInputStream(“c:/fileName.txt”); //filename.txt指要读入的文件名 int c=fis.read ();//读字节整数 } catch (FileNotFoundException e) { //捕获FileNotFoundException异常 System.out.println(“catchexception:”+e.getMessage()); } catch(IOException e) //捕获IOException异常 {System.out.println(“catchexception:”+e.getMessage()); } //在这里用e.getMessage()得到有关异常的信息
5.4 try-catch异常处理 当catch前面的try块中发生了一个异常,try-catch语句就会自动在try块后面的各个catch块中,找出与该异常类相匹配的参数。当参数符合以下三个条件之一时,就认为这个参数与产生的异常相匹配: (1) 参数与产生的异常的属于一个类; (2) 参数是产生的异常的父类; (3) 参数是一个接口时,产生的异常实现了这一接口。 当产生的异常找到了第一个与之相匹配的参数时,就执行包含这一参数的catch语句中的Java代码,执行完catch语句后,程序恢复执行,但不会回到异常发生处理继续执行,而是执行try-catch结构后面的代码。
5.5 finally子句 finally语句可以说是为异常处理事件提供的一个清理机制,一般是用来关闭文件或释放其他的系统资源,作为try-catch-finally结构的一部分,可以没有finally语句,如果存在finally语句,不论try块中是否发生了异常,是否执行过catch语句,都要执行finally语句。 带有finally子句的try-catch-finally语句的形式如下: try{ … } //…是正常执行的代码, 可能产生异常 catch (异常类1 e1){ … } //…是异常类1的处理代码 catch (异常类2 e2){ … }//…是异常类1的处理代码 …… catch (异常类n en){ … } //…是异常类1的处理代码 finally{ … } //…是执行清除工作的语句
5.5 finally子句 带有finally子句的try-catch-finally语句无论在try块中是否产生异常,也不管产生的异常是否会被捕获,finally中的语句最终都会被执行。具体的执行过程如下: (1) try块中的语句没有产生异常。在这种情况下,Java首先执行try块中的所有的语句,然后执行finally子句中的代码,最后执行try…catch..finally块后面的语句; (2) try块中的语句产生了异常,而且此异常在方法内被捕获。在这种情况下,Java首先执行try块中的语句,直到产生异常处,然后跳过此try块中剩下的语句,执行捕获此异常的catch子句的处理代码;然后执行finally子句中的代码; (3) 如果catch子句中没有重新抛出异常,那么Java将执行try…catch…finally块后面的语句。如果在catch子句又重新
5.5 finally字句 抛出了异常,那么Java将这个异常抛出给方法的调用者; (4) try块中产生了异常,而此异常在方法内没有被捕获。在这种情况下,Java将执行try块中的代码直到产生异常,然后跳过try块中的代码而转去执行finally子句中的代码,最后将异常抛出给方法的调用者。 例5.5 打开一个文件流,读入两个字符串,转化为整数,并求其和。 import java.io.*; class sum {public static voidmain(String args[]){ DataInputStream fis=null;
5.5 finally字句 try{ fis=new DataInputStream(new InputStream(“myfile.txt”)); //建立读入“myfile.txt”文件的输入流 String stra=fis.readln(); //读入一个字符串 int a=Integer.parseInt(stra); //把该字符串转化为整数 String strb=fis.readln(); int b=Integer.parseInt(strb); int c=a+b; System.out.println(c.toString());//输出c } catch(FileNotFoundexception e) { System.out.printIn(e.toString()); } catch(IOException e){ System.out.println(e.toString()); } catch(NumberFormatException e) { System.out.println(e.toString()); }
5.5 finally字句 finally{ if(fis= =null) {System.out.println(“DateInputStream not open!”) } //输入流没有打开 else { fis.close();//关闭输入流 System.out.println(“Close DalaInStream!”); } } } } 在这个程序中,输入流的关闭是放在finally块中统一完成的。如果不使用finally语句,程序就要考虑在发生不同异常的情况下,文件是否能关闭。 考虑到在不同的可能出现的运行情况下,程序会从不同的地方退出try/catch结构,为了知道哪些地方要加上关闭的语句,
5.5 finally字句 就不得不分析在所有可能出现的情况下,文件输入流能否关闭: (1) 文件正常运行,没有异常发生时,执行try块中全部语句,因而try块中要有关闭语句; (2) 产生文件没有找到异常,则输入流没有建立,也就不必关闭; (3) 产生读入字符引起的IO异常,进入相应的catch语句,需要在该catch块中关闭; (4) 产生字符串转化为整数时的类型不匹配异常,进入相应的catch语句,需要在该catch块中关闭。 根据这一分析,程序可能就要写成如下的形式: //不用finally语句的sum.java import java.io.*; class sum{ public static voidmain(String args[])//方法main()没抛出异常
5.5 finally字句 {DataInputStream fis=null; try {//try体可能有抛出的异常或程序错 fis=new DataInputStream(new FileInputStream(“myfile.txt”)); //建立读入“myfile.txt”文件的输入流 String stra=fis.readLine(); //读入一个字符串, 可能抛出异常 int a=Integer.parseInt(stra);//把该字符串转化为整数 String strb=fis.readLine();//读入一个字符串, 可能抛出异常 int b =Integer.parseInt(strb); //把该字符串转化为整数 int c=a+b; System.out.println(c.toString());//输出c fis.close(); } catch(FileNotFoundException e) { System.out.println(e.toString()); }
5.5 finally字句 catch(IOException e) {System.out.println(e.toString()); fis.close(); } catch(NumberFormatException e) {System.out.println(e.toString()); fis.close();} } } 很明显,在程序中有三处地方要执行fis.close()语句,使程序代码重复,而且今后进行修改时也容易出错。所以用finally语句的一个好处,就是把方法中所有清除状态和关闭文件的语句放在一起,不但避免了代码重复,更减少了出现遗漏语句的现象,对程序将来的修改也较为集中和方便。
5.6正确地使用异常 由于异常使用起来非常方便,以至于在很多情况下可能会滥用异常。但是,使用异常处理会降低程序运行的速度,如果在程序中过多地使用异常处理,程序的执行速度会显著地降低。这里给出几点建议,来帮助掌握好使用异常处理的尺度。 (1) 在可以使用简单的测试就能完成的检查中,不要使用异常来代替它。例如: if (ins!=null) //使用ins引用对象 { …} (2) 不要过细地使用异常。最好不要到处使用异常,更不要在循环体内使用异常处理, 可以将它包裹在循环体外面. (3) 不要捕获了一个异常而又不对它做任何的处理。如下例所示:
5.6正确地使用异常 try { …… //正常执行的代码 } catch(Exception e) { } (4) 将异常保留给方法的调用者并非不好的做法。 对于有些异常,将其交给方法的调用者去处理是一种更好的处理办法。
小结 异常处理把Java程序各种可能出现的错误都看作异常,集中起来统一处理。程序员只需要说明何处理可能的出现异常,如何处理即可。 throws抛出异常和方法说明联系在一起,是针对以下情况:调用的方法抛出了异常、检测到了错误并使用throw语句抛出异常、程序代码有错误从而异常。 try-catch异常处理机制。当try体中发生了一个异常,try-catch语句就会自动在try体后面的各个catch语句中,找出与该异常类相匹配的参数,就执行包含这一参数的catch语句中的java代码,执行完catch语句后,程序恢复执行,但不会回到异常发生处理继续执行,而是执行try-catch结构后面的代码。 finally语句为异常处理事件提供的一个清理机制。
习题 1.什么是异常?简述Java的异常处理机制。 2.系统定义的异常与用户自定义的异常有何不同?如何使用这两类异常? 3. 编写从键盘读入10个字符放入一个字符数组,并在屏幕上显示它们的程序,程序中处理数组越界异常。