一、什么是异常
异常指的是导致程序中断执行的一种指令流。
若程序中有一处错,程序在中途运行停止,如下:
public class Test {
public static void main(String[] args) {
System.out.println("1111111111");
System.out.println("2222222"+ (9/0));
System.out.println("3333333333");
}
}
1111111111
Exception in thread "main" java.lang.ArithmeticException: / by zero
at Exception.Test.main(Test.java:9)
可以看出程序未按正常流程执行,而是中断了,这个就是运行时异常,导致程序不能顺利执行完毕。
二、异常处理机制
若这个导致的中断语句是非核心语句,我们不想让这个非核心语句影响整个程序的运行,而继续向下执行,就需要一个异常处理机制了。异常处理机制由try、catch、finally三个关键字来完成,基本语法格式如下:
try {
// 可能出现异常的语句
} catch (异常类型 异常对象){
// 异常处理语句
} catch (异常类型 异常对象){
// 异常处理语句
} finally {
// 不管是否有异常都要执行的语句
}
例如上面的代码,第二句可能会有异常,就这第二句处加上try即可,如下:
public class Test {
public static void main(String[] args) {
System.out.println("1111111111");
try {
System.out.println("2222222"+ (9/0));
} catch (ArithmeticException e) {
e.printStackTrace();
}
System.out.println("3333333333");
}
}
结果:
1111111111
java.lang.ArithmeticException: / by zero
at Exception.Test.main(Test.java:10)
3333333333
可以看出,第二个打印虽然还是有异常,但是因为提前进行了异常处理,不影响后面代码的执行,第三个打印正常执行了。
这里注意finally里面的语句不管异常是否出现都会被执行。
三、异常处理流程
(1)在程序运行的过程中才会产生异常,而一旦程序执行中产生了异常之后将自动实例化指定异常类;
(2)对于没有手写异常处理的,则会采用JVM默认异常处理方式,首先进行异常信息打印,然后直接退出当前程序;
(3)若存在异常处理,那么这个产生异常类的实例化对象会被try捕获,然后与catch里的异常类进行匹配对比,若匹配则用这个catch中的处理语句进行处理,若不匹配则继续匹配下一个catch;
(4)不管是否处理,finally语句始终会被执行。
四、Error和Exception的区别
Error:是程序未执行时出现的错误,开发者无法处理;
Exception:程序执行时出现的异常,开发者可以处理,实际开发中只需要关注异常即可;
五、异常继承关系
六、多个异常处理范围问题
类型范围大的异常应该放在最后一个catch中,若放在前面的catch中则后面的catch将不在匹配执行。
七、throws关键字
在程序运行时可能会产生异常,如果想明确告诉他人是何种异常可以使用throws关键字在方法上声明。
class DiveMethod{
public static double div(int x, int y) throws ArithmeticException{
return x/y;
}
}
public class ThrowsTest {
public static void main(String[] args) {
try {
System.out.println(DiveMethod.div(100, 6));
} catch (ArithmeticException e) {
e.printStackTrace();
}
}
}
上面的DiveMethod的div()方法就用throws声明了可能产生的异常,且该异常在调用处处理,即谁调用谁处理(也可以不处理,继续向上抛出)。若继续抛出则如下:
class DiveMethod{
public static double div(int x, int y) throws ArithmeticException{
return x/y;
}
}
public class ThrowsTest {
public static void main(String[] args) throws ArithmeticException {
System.out.println(DiveMethod.div(100, 6));
}
}
八、throw关键字
throws是在方法处声明该方法可能出现的异常类型,throw则主要表示手动进行异常的抛出。
public class ThrowsTest {
public static void main(String[] args) throws ArithmeticException {
try {
throw new Exception("手动抛出异常对象");
} catch (Exception e) {
e.printStackTrace();
}
}
}
九、throws和throw的区别
- throws:在方法定义上使用,表示此方法中可能出现的异常,并且告诉调用者要处理该异常;
- throw:在代码块上使用,手动进行异常对象的抛出。
十、RuntimeException和Exception的区别
- RuntimeException是Exception的子类;
- RuntimeException标识的异常可以不强制处理,Exception标识的异常必须强制性处理。
十一、自定义异常类
JDK定义的异常类不够使用时,就需要自定义异常类。实现方式为继承Exception或者RuntimeException。
// 自定义异常类
class SelfExceptionDemo extends Exception {
public SelfExceptionDemo(String msg){
super(msg);
}
}
class Div {
public static double divTest(int x, int y) throws SelfExceptionDemo {
return x/y;
}
}
public class SelfException{
public static void main(String[] args) {
try {
Div.divTest(10,4);
} catch (SelfExceptionDemo selfExceptionDemo) {
selfExceptionDemo.printStackTrace();
}
}
}