认识异常:
异常就是在程序运行过程中所发生的不正常事件,如:找不到文件,运算错误(除数为零)、数组越界、加载一个不存在的类、对null对象进行操作、类型转换错误等。异常会中断程序的运行。
首先从一个实例了解下异常:
实例:编写一个程序实现根据输入的除数和被除数,计算出商,最后输出"感谢你使用本程序"
public class Test {
/**异常代码演示
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner input= new Scanner(System.in);
System.out.println("请输入一个除数:");
int num1=input.nextInt();
System.out.println("请输入除数:");
int num2=input.nextInt();
System.out.println(String.format("%d/%d=%d", num1, num2,num1/num2));
System.out.println("感谢使用本程序!");
}
}
思考一下几个问题:
- 在正常情况下,输入的结果正确无误
- 当被除数或除数输入不是整数时,是不是有异常抛出?
- 当被除数输入0时,程序也会发生异常,出现了这种异常我们该怎么去做呢?
首先想到是不是可以通过判断选择结构呢?
实例:
public class ExceptionDemo {
public static void main(String[] args) {
Scanner input= new Scanner(System.in);
System.out.println("输入被除数:");
int num1=0;//定义变量用来保存输入的被除数
if(input.hasNextInt()){
//判断输入的数值是不是整数
num1=input.nextInt();
}else{
//如果输入的不是整数
System.err.println("输入的不是整数,程序将退出");
System.exit(2);
}
System.out.println("请输入除数:");
int num2=0;
if(input.hasNextInt()){
//判断输入的数值是不是整数
num2=input.nextInt();
if(0==num2){
//判断是不是0
System.err.println("输入的除数是0,程序退出");
System.exit(2);
}
}else{
System.err.println("输入的除数不是整数,程序退出");
System.exit(2);
}
System.out.println(String.format("%d/%d=%d", num1, num2,num1/num2));
System.out.println("感谢使用本程序!");
}
}
总结:
通过if-else语句处理异常的缺点:
- 代码臃肿
- 程序员把大量的精力用在处理异常上,开发效率低下
- 很难找出所用的异常
- 异常和业务代码交织在一起维护性难度大
此时我们就可以使用异常处理机制,对上面的问题进行解决。
异常概念:
异常:在Java语言中,将程序执行中发生的不正常情况称为“异常”。 (开发过程中的语法错误和逻辑错误不是异常)
Java程序在执行过程中所发生的异常事件可分为两类:
1.**Error:**Java虚拟机无法解决的严重问题。如:JVM系统内部错误、资源 耗尽等严重情况。比如:StackOverflowError和OOM。一般不编写针对性 的代码进行处理
实例:
public class ErrorTest {
public static void main(String[] args) {
//1.栈溢出:java.lang.StackOverflowError
// main(args);
//2.堆溢出:java.lang.OutOfMemoryError
Integer[] arr = new Integer[1024*1024*1024];
}
}
一般情况下,我们对此类错误不做代码上的补救。
2.Exception: 其它因编程错误或偶然的外在因素导致的一般性问题,可以使 用针对性的代码进行处理。
例如: 1).空指针访问
2)试图读取不存在的文件
3)网络连接中断
4)数组角标越界
处理此类异常常用的5个关键字:
- try:执行可能产生异常的代码
- catch:捕获异常,一旦try中的代码出现异常,在此进行捕获处理
- finally:无论是否产生异常,该语句块都会执行
- throw :手动抛出异常
- throws:声明方法可能要抛出的异常
使用try-catch代码块:
try{
//可能产生异常的代码块
}catch(异常类型 e){
//对异常进行出来的代码块
}
实例:
public class ExceptionDemo1 {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
Scanner input= new Scanner(System.in);
System.out.println("请输入一个除数:");
int num1=input.nextInt();
System.out.println("请输入除数:");
int num2=input.nextInt();
System.out.println(String.format("%d/%d=%d", num1, num2,num1/num2));
System.out.println("感谢使用本程序!");
} catch (Exception e) {
// TODO: handle exception
System.err.println("出现错误!被除数和除数必须为整数,并且除数不能为0");
e.printStackTrace();
}
}
}
使用try-catch-finally处理异常:
public class ExceptionDemo2 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
try {
System.out.println("请输入被除数:");
int num1 = input.nextInt();
System.out.println("请输入除数:");
int num2 = input.nextInt();
System.out.println(String.format("%d/%d=%d", num1,num2,num1/num2));
} catch (Exception e) {
System.err.println("出现错误:除数和被除数必须是整数,并且除数不能为0");
System.out.println(e.getMessage());
}finally{
System.out.println("谢谢使用本程序");
}
}
}
Try-catch-finally结构中try语句块必须存在,catch、finally语句块为可选,但是两者必须出现其中一个
执行流程:
- try中的所有语句正常执行完毕,finally语句就会执行。
- try中发生异常,无论catch能否捕捉到异常,finally中的语句都将被执行
※注意:
即使try语句、catch语句块中存在return语句,finally语句块中的语句也会执行,当发生异常时的语句执行顺序是:执行try和catch语句块中return之前的语句→finally语句→再执行try或catch中的return语句
异常体系结构
java.lang.Throwable
|-----java.lang.Error:一般不编写针对性的代码进行处理。
|-----java.lang.Exception:可以进行异常的处理
|------编译时异常(checked)
|-----IOException
|-----FileNotFoundException
|-----ClassNotFoundException
|------运行时异常(unchecked,RuntimeException)
|-----NullPointerException
|-----ArrayIndexOutOfBoundsException
|-----ClassCastException
|-----NumberFormatException
|-----InputMismatchException
|-----ArithmeticException
Throwable: 有两个重要的子类:**Exception(异常)**和 Error(错误),二者都是 Java 异常处理的重要子类,各自都包含大量子类。
Error(错误):是程序无法处理的错误,表示运行应用程序中较严重问题。大多数错误与代码编写者执行的操作无关,而表示代码运行时 JVM(Java 虚拟机)出现的问题。例如,Java虚拟机运行错误(Virtual MachineError),当 JVM 不再有继续执行操作所需的内存资源时,将出现 OutOfMemoryError。这些异常发生时,Java虚拟机(JVM)一般会选择线程终止。
Exception(异常):是程序本身可以处理的异常。根据处理方式Exception又分为运行时异常和编译时异常
运行时异常:
- 是指编译器不要求强制处置的异常。一般是指编程时的逻辑错误,是程序 员应该积极避免其出现的异常。java.lang.RuntimeException类及它的子 类都是运行时异常。
- 对于这类异常,可以不作处理,因为这类异常很普遍,若全处理可能会对 程序的可读性和运行效率产生影响。
编译时异常:
1, 是指编译器要求必须处置的异常。即程序在运行时由于外界因素造成的一 般性异常。编译器要求Java程序必须捕获或声明所有编译时异常。
2.对于这类异常,如果程序不处理,可能会带来意想不到的结果.
异常处理方式
- try-catch-finally:如上例
- throws + 异常类型
实例:
package com.qwy;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class ExceptionTest2 {
public static void main(String[] args){
try {
method1();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//抛出异常
public static void method1() throws FileNotFoundException,IOException{
File file = new File("hello1.txt");
FileInputStream fis = new FileInputStream(file);
int data = fis.read();
while(data != -1){
System.out.print((char)data);
data = fis.read();
}
fis.close();
System.out.println("hahaha!");
}
}
关于手动抛出异常和自定义异常后期补充