在程序运行时,很多问题不是靠代码能够避免的,比如用户输入数据格式不符合预期,读取文件不存在,网络不可用或不通畅等。
在Java语言中,将程序执行过程中发生的不正常情况称为“异常”。(开发过程中的语法错误和逻辑错误不是异常)
Java程序在执行过程中所发生的异常事件可分为两类:
对于这些异常,如果在编写程序时没有进行错误的检测以及处理(消息提示等),则会终止程序的运行,这是用户不希望看到的。
是指编译器不要求强制处置的异常。一般是指编程时的逻辑错误,是程序员应该积极避免其出现的异常。
java.lang.RuntimeException类及它的子类都是运行时异常。 对于这类异常,可以不作处理,因为这类异常很普遍,若全处理可能会对程序的可读性和运行效率产生影响。
是指编译器要求必须处置的异常。即程序在运行时由于外界因素造成的一般性异常。编译器要求java程序必须捕获或声明所有编译时异常。
对于这类异常,如果程序不处理,可能会带来意想不到的结果。
个人总结:两种异常的差别在于,编译时异常是编译时就必须要告诉虚拟机如果万一出错了该怎么处理,要求更严格,这样可以避免在运行时可能出现异常导致程序终止。而运行时异常则没有这个限制,好处是没有太多的异常处理代码,不会影响代码的可读性和运行效率,坏处是没有捕获异常的话运行时会终止程序,所以这类异常应该在编写程序的过程中尽量避免,比如对于可能为空指针的变量要异常注意。
Java采用异常处理机制,将异常处理的程序代码集中在一起,与正常的程序代码分开,使得程序简洁,并易于维护。
Java提供的是异常处理的抓抛模型。
异常处理是通过try-catch-finally语句实现的。
支持嵌套:
public void test3() {
try {
int j = 10 / 0;
} catch (Exception e) {
System.out.println(e.getMessage() + 1);
try {
int j = 10 / 0;
} catch (Exception e) {
System.out.println(e.getMessage() + 2);
}
} finally {
try {
int j = 10 / 0;
} catch (Exception e) {
System.out.println(e.getMessage() + 3);
}
}
}finally一定会执行:
public static int method1() {
try {
System.out.println(10/0);
// 执行到这里会先执行finally中的代码,若finally中有return,则这里的的return 1不会执行
return 1;
} catch (Exception e) {
System.out.println("捕获到异常时这里会执行");
// 执行到这里会先执行finally中的代码,若finally中有return,则这里的的return 3不会执行
// return 3;
} finally {
System.out.println("这里一定会执行");
// return 2;
}
System.out.println("这里可能会执行");
return 4;
}牛客网的一道题:
public class Test {
public static void main(String [] args){
System.out.println(new B().getValue());
}
static class A{
protected int value;
public A(int v) {
setValue(v);
}
public void setValue(int value){
this.value = value;
}
public int getValue(){
try{
value++;
return value;
} catch(Exception e){
System.out.println(e.toString());
} finally {
this.setValue(value);
System.out.println(value);
}
return value;
}
}
static class B extends A{
public B() {
super(5);
setValue(getValue() - 3);
}
public void setValue(int value){
super.setValue(2 * value);
}
}
} 输出为:22 34 17 注意: (1)try中的return为value++后的值,而不是执行finally后的value值(虽然finally确实执行了) (2)对B调用的是B中重载后的setValue
如果一个方法(中的语句执行时)可能生成某种异常,但是并不能确定如何处理这种异常,则此方法应显式地声明可能抛出的异常类,表明该方法将不对这些异常进行处理,而由该方法的调用者负责处理。
public static void method1() throws FileNotFoundException, IOException{
FileInputStream fis = new FileInputStream(new File("hello1.txt"));
int b;
while((b = fis.read()) != -1){
System.out.print((char)b);
}
fis.close();
}注意:重写方法不能抛出比被重写方法范围更大的异常类型。在多态的情况下,对重写方法的异常的捕获按父类中方法声明的异常处理。
Java异常类对象除在程序执行过程中出现异常时由系统自动生成并抛出,也可根据需要人工创建并抛出。
语法为:
throw Throwable或其子类的实例;throw单独存在,紧跟着throw语句不要定义语句,因为执行不到。(跟return道理一样)
public class MyException extends Exception{
static final long serialVersionUID = -70348975766939L;
public MyException(){
}
public MyException(String msg){
super(msg);
}
}Java的异常处理过程为:抛出异常 -> (往上逐层抛出) -> 捕获并处理异常。
以上笔记参考自尚硅谷