一、了解异常与错误

概述:在软件开发过程中,程序中出现错误是不可避免地的。而异常(Exception)是值程序运行中由代码产生的一种错误。在不支持异常处理的程序设计语言中,每一个运行错误必须由程序员手动控制。不仅增加工作量而且麻烦。Java语言的异常处理机制避免了这些问题,在处理的过程中,把程序运行时错误的管理带到了面向对象的世界中。

二、错误的分类

——按照错误的性质可将程序错误分为语法错,语义错和逻辑错三种。
语法错:违法语法规则
语义错:语法正确,但在语义上错误,如除数为0,输入格式错;
逻辑错:程序不能实现程序员的设计意图,计算结果与预期结果不一致。、

——按照错误的严重程度的不同,将程序运行时出的错分为错误(Error)和异常(Exception)。
1、错误:致命性的,用户程序无法处理,如内存溢出,虚拟机错误,栈溢出等,Error类是所有错误类的父类,常见的Error有:NotClassDeFountError(类未定义错误),OutofMemoryError(内存溢出错误),StackOverFlowError(栈溢出错误)。
2、异常:非致命性的,可编制程序捕获和处理,如运算时除数为0,Exception类是所有异常类的父类。

三、异常的分类

——非检查型异常
1、不能期望程序捕获的异常(例如数组越界,除零等)
2、继承自RuntimeException
3、在方法中不需要声明,编译器也不进行检查
——检查型异常
1、其他类型的异常
2、如果被调用的方法抛出一个类型为E的检查型异常,那么调用者必须捕获E或者也声明抛出E(或者E的一个父类),对此编译器要进行检查

四、异常类的层次结构

Java语法错误已在接口定义方法 java 语法错误是异常吗_抛出异常

五、异常处理

1、检查型异常
对于检查型异常,Java强迫程序必须进行处理。处理方法有两种:
——声明抛出异常
不在当前方法内处理异常,而是把异常抛出到调用方法中
——捕获异常
使用try{}catch(){}块,捕获到所发生的异常,并进行相应的处理

声明抛出异常
将从两个方面介绍抛出异常,一是抛出异常的方法,二是调用方法处理异常

——在捕获一个异常前,必须有一段代码生成一个异常对象并把它抛出,根据异常类型的不同,抛出异常的方法也不同。
(1)系统自动抛出的异常
(2)指定方法抛出异常
所有系统定义的运行时异常都可以由系统自动抛出。而指定方法抛出异常需要使用关键字throw或throws来明确指定方法内抛出异常。如用户自定义的异常不可能依靠系统自动抛出,此时必须借助throw或throws语句来定义何种情况算是产生了此种异常对应的错误,并应该抛出这个异常。
抛出异常的两种方式:
方式一:在方法体内使用throw语句抛出异常对象,其语句格式:
throw 由异常类产生的对象;
其中由异常类产生的对象是一个从Throwable派生的异常类对象。
方式二:
在方法头部添加throws子句表示方法将抛出异常,
【修饰符】返回值类型 方法名(【参数列表】)throws 异常类列表
说明:异常类多于一个时用逗号“,”隔开。
——由调用方法处理异常
由一个方法抛出异常后,该方法内又没有处理异常的语句,则系统则会将异常向上传递,由调用它的方法来处理这些异常,若上层调用方法仍没有处理异常的语句,则可以再往上追溯到更上层,这样可以一层一层的向上追溯,一直可以追溯到main()方法,这时JVM肯定要进行处理,这样编译就可以通过了。也就是说,如果某个方法声明抛出异常,则调用它的方法必须捕捉并处理异常,否则会出现错误。
(如果所有的方法都选择了抛出此异常,最后 JVM将捕获它,输出相关的错误信息,并终止程序的运行。在异常被抛出的过程中, 任何方法都可以捕获它并进行相应的处理)
代码演示:

public void openThisFile(String fileName) 
     throws java.io.FileNotFoundException {     
      //code  for method 
 }

public void getCustomerInfo() 
    throws java.io.FileNotFoundException {      
      // do something    
        this.openThisFile("customer.txt");  
        // do something 
     }

说明:
如果在openThisFile中抛出了FileNotfoundException异常,getCustomerInfo将停止执行,并将此异常传送给它的调用者

捕获异常:

语法格式

try {
 statement(s)
 } catch (exceptiontype name) {
 statement(s)
 } finally {
 statement(s)
 }


说明
try 语句
其后跟随可能产生异常的代码块
catch语句
其后跟随异常处理语句,通常用到两个方法
getMessage() – 返回一个字符串对发生的异常进行描述。
printStackTrace() – 给出方法的调用序列,一直到异常的产生位置
finally语句
不论在try代码段是否产生异常,finally 后的程序代码段都会被执行。通常在这里释放内存以外的其他资源
注意事项
在类层次树中,一般的异常类型放在后面,特殊的放在前面
代码演示:

//读入两个整数,第一个数除以第二个数,之后输出
import java.io.*; 
public class ExceptionTester { 
     public static void main(String args[]) { 
         System.out.println("Enter the first number:"); 
         int number1 = Keyboard.getInteger(); 
         System.out.println("Enter the second number:"); 
         int number2 = Keyboard.getInteger(); 
         System.out.print(number1 + " / " + number2 + "=");         
         int result = number1 / number2; 
         System.out.println(result); 
     } 
}
//其中,Keyboard类的声明如下
import java.io.*; 
 class Keyboard{
	static BufferedReader inputStream = new BufferedReader 
                  (new InputStreamReader(System.in)); 	
	public static int getInteger() { 
    		try { 
         return (Integer.valueOf(inputStream.readLine().trim()).intValue()); 
       } catch (Exception e) { 
        e.printStackTrace(); 
        return 0; 
        } 
     }
     public static String getString() { 
     try{
  	  return (inputStream.readLine()); 
     }catch (IOException e) 
        { return "0";}  
}
}

运行结果:
运行结果

Enter the first number:
 140
 Enter the second number:
 abc
 java.lang.NumberFormatException: abc
 at java.lang.Integer.parseInt(Integer.java:426)
 at java.lang.Integer.valueOf(Integer.java:532)
 at Keyboard.getInteger(Keyboard.java:10)
 at ExceptionTester.main(ExceptionTester.java:7)
 140 / 0=Exception in thread “main” java.lang.ArithmeticException: / by zero
 at ExceptionTester.main(ExceptionTester.java:10)

说明:try块后可跟多个catch块处理产生的多个异常。

六、生成异常对象

——三种方式
1、由Java虚拟机生成
2、由Java类库中的某些类生成
3、在程序中生成自己的异常对象,也即是异常可以不是出错产生,而是人为地抛出
——生成异常对象都是通过throw语句实现,生成的异常对象必须是Throwable或其子类的实例
throw new ThrowableObject();
ArithmeticException e = new ArithmeticException();
throw e;

七、声明自己的异常类

除使用系统预定义的异常类外,用户还可声明自己的异常类
自定义的所有异常类都必须是Exception的子类
一般的声明方法如下

public class MyExceptionName extends SuperclassOfMyException {
 public MyExceptionName() {
 super(“Some string explaining the exception”);
 }
 }