目录
1.异常体系
通常异常可以分为编译期错误和运行时错误
- 编译期错误会导致源码编译成字节码的时候报错,这种错误的危害性比较小,因为绝大数编译器都会提示,比如少了分号之类的语法错误.
- 运行时错误才是开发者主要需要解决的错误,在程序已经运行的过程中,发生的错误,这种错误可以程序终止,也可以泛指程序虽然能正常运行,但是效果违背我们的意愿.
1.1异常的分类
这里的异常,一般指的是运行时的错误
Throwable是Java异常体现中的父类
Error:一般指JVM出现不可逆转的错误,这种错误靠Java异常体现是无法挽救,比较常见的就是OutOfmemoryError(内存不够用)和LinkageError(其子类错误更常见,这种异常直接出现的时候,一般是因为多个类加载器在同时作用且互相作用)
Exception:这边一般会分为非检查异常(UncheckedException)和检查异常(CheckException)
- 非检查异常指的是 编译器不要求强制处理的异常,主要由RuntimeException以及其子类构成,开发者可以处理,也可以不处理让程序异常中断,这类异常一般是因为程序设计本身造成的
- 检查异常指不可预知和避免的异常,一般是由外界因素导致,比如说程序读取一个文件,但文件是不存在的.另外异常检查Java强制要求开发者做处理
- Error其实也是非首检类型
1.2 异常处理
Java围绕异常处理,提供了五个关键字
try:用来包裹可能产生异常的代码.
catch:捕获异常,通常在catch代码块中处理异常
final:fianlly语句块一般用作收尾处理,因为产不产生异常,fianlly语句块中的代码都会执行
throws:声明异常,主要用在方法的声明中用来表示该方法可能会抛出什么异常
throw:代表动作,手动抛出一个异常,主要用在方法中.
public static void main(String[] args) {
/**
* try块不能单独使用,需要配置至少一个catch或者一个finally语句块
*/
try {
if (1 == 1) {
// int i = 1 / 0;
int i = 1 / 1;
}
//catch' or 'finally' expected
} catch (Exception e) {
//如果代码走进catch块,说明捕获了一个Exception类型的异常
System.out.println("出现异常了");
//打印该异常的堆栈信息
e.printStackTrace();
}finally {//无论try块中产不产生异常,finally不受影响
System.out.println("finally语句块被执行");
}
}
摘要:1.try块不能单独使用,需要配置至少一个catch或者一个finally语句块
2.如果代码块走进了catch块,说明捕获了一个Exception类型的异常
3.无论try块中产不产生异常,fianlly都不受影响.
throws关键字
throws的作用就是告诉调用方要对异常进行处理(异常类型不一定准确)
public static void main(String[] args) {
method1();
}
public static void method1(){
method2();
}
public static void method2() {
try {
method3();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void method3() throws Exception{
if (1 == 1) {
int i = 1 / 0;
}
}
上面的例子是个调用链: main()-->method1()-->method2()-->method3()
其中使用throws关键字声明method3可能会抛出异常,所以作为调用方需要处理可能抛出的异常
注意:只有抛出Exception这种受检异常,调用方那边才提示强制处理,如果声明是可能抛出非受检异常,则调用方不用强制处理.
调用方选择处理的方式有两种:
- 继续将异常抛给调用方,可以一直抛给JVN虚拟机
- 用try{}catch{}捕获并进行处理
throw关键字
一般作用在方法内
public static void method3() throws Exception {
try {
if (1 == 1) {
int i = 1 / 0;
}
} catch (Exception e) {
System.out.println("出错了");
//捕获异常之后,再抛给调用方也是一种处理方式
//这里抛异常出去,也要注意,你抛的是checked还是unchecked,如果是checked,则还需要
//在方法声明处加上throws来声明该方法会抛出异常(其实也可以在抛出的地方,加try..catch,但
是一般不这么做)
throw new Exception("无中生有的异常");
// throw new ArithmeticException("无中生有的算数异常");
}
}
1.3多catch语句块
public static void method2() {
try {
method3();
} catch (ArithmeticException e) {
System.out.println("算数异常");
} catch (NullPointerException e) {
System.out.println("空指针异常");
} catch (Exception e) {
System.out.println("未知异常");
}
}
多catch中,父类Exception异常不能在各种子类异常(如 ArithmeticException,NullPpoionterException)的上面做捕获处理.而"兄弟"同级的异常之间的顺序无所谓.
1.4 finally补充
面试常问: finally语句块中的语句一定会被执行吗?
答案: 不一定
第一种情况: try{}块都还没有执行, 方法就返回了 return了
public static void main(String[] args) {
if (1 == 1) {
//try块都没有执行,方法就return了
return;
}
try {
if (1==1) {
int i = 1 / 0;
// int i = 1 / 1;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
System.out.println("finally语句块执行了");
}
}
第二种: 直接终止了JVM虚拟机
public static void main(String[] args) {
if (1 == 1) {
//try块都没有执行,方法就return了
return;
}
try {
//终止JVM
System.exit(0);
if (1==1) {
int i = 1 / 0;
// int i = 1 / 1;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
System.out.println("finally语句块执行了");
}
}
第三种:当线程在try/catch块中被执行,然后被杀了,或者中断了,fianlly可能不会执行了