推荐链接:
Java 异常处理 - 菜鸟
Java IO详解系列
Java中的异常和处理详解
异常的三种类型
- **检查性异常:**最具代表的检查性异常是用户错误或问题引起的异常,这是程序员无法预见的。例如要打开一个不存在文件时,一个异常就发生了,这些异常在编译时不能被简单地忽略。
- 运行时异常: 运行时异常是可能被程序员避免的异常。与检查性异常相反,运行时异常可以在编译时被忽略。
- 错误: 错误不是异常,而是脱离程序员控制的问题。错误在代码中通常被忽略。例如,当栈溢出时,一个错误就发生了,它们在编译也检查不到的。
体系结构


Throwable:JAVA中所有错误与异常的父类。
|–Error:用来指示运行时环境发生的错误,程序通常不捕获错误。严重故障时才会发生错误,比如说内存溢出,一般地,程序不会从错误中恢复。
|–Exception:在编写程序时应该捕获或处理的异常。
|–RuntimeException及其子类:运行时异常,程序中可以选择捕获,也可以不处理。
|–非RuntimeException:检查性异常,在编写程序时必须捕获或处理的异常。否则.java文件无法编译生成.class文件,即程序不能编译通过。
编程习惯:如果在函数体内用throw抛出了某种异常,最好要在函数名中加throws抛异常声明,然后交给调用它的上层函数进行处理。
说明:某个函数或某段程序块不管会不会、有没有可能抛出异常,都可以加try{…}catch{…}去捕捉它。
OutOfMemoryError:当 Java 虚拟机因为内存不足而无法分配对象时抛出,并且垃圾收集器无法提供更多内存。虚拟机可以构造 OutOfMemoryError 对象,就好像禁用了抑制或者堆栈跟踪不可写一样。
StackOverflowError:当由于应用程序递归太深而发生堆栈溢出时引发。
IOError:发生严重 IO 错误时抛出。
异常处理
A:JVM的默认处理
把异常的名称,原因,位置等信息输出在控制台,但是后面的程序不能继续执行了。
B:自己处理:try…catch…finally,后面的程序可以继续执行
格式:
try{
可能发生异常的代码,用于捕获异常。这里面的代码越少越好。
}catch(异常名 变量){
处理异常的代码;
必须要有内容,哪怕是给出一个简单的提示
}catch(异常名 变量){
能明确的尽量明确,不要用大的来处理。
平级关系的异常谁前谁后无所谓,如果出现了父子关系,父必须在子后面。
}finally{
一定执行的代码;(比如释放资源)
}
1.try块不能单独使用,必须与catch块或finally块一起出现。
2.一个try语句中可以出现0个或多个catch块。
3.当try块中的代码发生异常时,try块中的代码会中止执行。跳转到对应的catch块中处理异常。
4.可以使用Exception在catch块中处理所有的异常。
5.Exception必须出现在最后一个catch块中。
6.无论程序是否出现异常,finally中的代码一定执行。
7.不建议在finally块中写return语句。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| public class ExceptionDemo2 { public static void main(String[] args) { int a = 10; int b = 0; int[] arr = { 1, 2, 3 };
try { System.out.println(a / b); System.out.println(arr[3]); System.out.println("这里出现了一个异常,你不太清楚是谁,该怎么办呢?"); } catch (ArithmeticException e) { System.out.println("除数不能为0"); } catch (ArrayIndexOutOfBoundsException e) { System.out.println("你访问了不该的访问的索引"); } catch (Exception e) { System.out.println("出问题了"); }
try { System.out.println(a / b); System.out.println(arr[3]); } catch (ArithmeticException | ArrayIndexOutOfBoundsException e) { System.out.println("出问题了"); } System.out.println("over"); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
|
public class ExceptionDemo { public static void main(String[] args) { String s = "2014-11-20"; SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); try { Date d = sdf.parse(s); System.out.println(d); } catch (ParseException e) { e.printStackTrace();
System.out.println(e.getMessage());
System.out.println(e.toString());
}
System.out.println("over"); } }
|
throw与throws
1.throw:
在方法体体内手动的抛出一个异常。后面跟的是异常对象名,并且只能是一个。
throw抛出的是一个异常对象,说明这里肯定有一个异常产生了
2.throws:
在方法的声明上,后面跟的是异常的类名,可以是多个。说明调用此方法时,方法可能抛出哪些异常。
throws是声明方法有异常,是一种可能性,这个异常并不一定会产生。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
|
public class ExceptionDemo { public static void main(String[] args) {
try { method2(); } catch (Exception e) { e.printStackTrace(); } }
public static void method() { int a = 10; int b = 0; if (b == 0) { throw new ArithmeticException(); } else { System.out.println(a / b); } }
public static void method2() throws Exception { int a = 10; int b = 0; if (b == 0) { throw new Exception(); } else { System.out.println(a / b); } } }
|
自定义异常
继承自Exception或者RuntimeException,只需要提供无参构造和一个带参构造即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
|
public class StudentDemo { public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.println("请输入学生成绩:"); int score = sc.nextInt();
Teacher t = new Teacher(); try { t.check(score); } catch (MyException e) { e.printStackTrace(); } } }
class Teacher { public void check(int score) throws MyException { if (score > 100 || score < 0) { throw new MyException("分数必须在0-100之间"); } else { System.out.println("分数没有问题"); } }
}
class MyException extends Exception { private static final long serialVersionUID = 1L;
public MyException() { }
public MyException(String message) { super(message); } }
|
注意事项
A:父的方法有异常抛出,子的重写方法在抛出异常的时候必须要小于等于父的异常
B:父的方法没有异常抛出,子的重写方法不能有异常抛出,只能try,不能throws
C:父的方法抛出多个异常,子的重写方法必须比父少或者小
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| public class ExceptionDemo { public static void main(String[] args) { Zi zi = new Zi(); zi.method(); } }
class Fu { public void show() throws Exception { }
public void method() { } }
class Zi extends Fu { @Override public void show() throws ArithmeticException {
}
@Override public void method() { String s = "2014-11-20"; SimpleDateFormat sdf = new SimpleDateFormat(); Date d = null; try { d = sdf.parse(s); } catch (ParseException e) { System.out.println("日期格式有误!"); } System.out.println(d); } }
|
finally关键字
A:finally用于释放资源,它的代码永远会执行。特殊情况:在执行到finally之前jvm退出了
B:面试题
a:final,finally,finalize的区别?
final:最终的意思,可以修饰类,成员变量,成员方法
修饰类,类不能被继承
修饰变量,变量是常量
修饰方法,方法不能被重写
finally:是异常处理的一部分,用于释放资源。
一般来说,代码肯定会执行,特殊情况:在执行到finally之前jvm退出了
finalize:是Object类的一个方法,用于垃圾回收
b:如果在catch里面有return,请问finally还执行吗?如果执行,在return前还是后
会,前。
实际上在中间。
C:异常处理的变形
try…catch…finally
try…catch…
try…catch…catch…
try…catch…catch…fianlly
try…finally