java的异常处理通过5个关键字来实现的:try、catch、finally、throw、throws
1. try-catch-finally
public class TestException {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
try {
System.out.println("请输入总分");
int sum = input.nextInt();
System.out.println("请输入人数");
int count = input.nextInt();
int result = sum / count;
System.out.println("result = " + result);
return;
}catch (Exception e) {
e.printStackTrace(); // java.util.InputMismatchException at ...
System.out.println(e.toString()); // java.util.InputMismatchException
System.out.println(e.getMessage()); // null
System.err.println("输入非数字");
// throw e; // 继续向上抛出异常,catch后面的语句就不执行了
}
System.out.println("bye");
}
}
try-catch执行情况
- try块中代码没有出现异常:不执行catch块代码,执行catch后的代码
- try块中代码出现异常,catch中异常类型匹配(相同或父类):执行catch块代码,执行catch后的代码
- try块中代码出现异常,catch中异常类型不匹配:不执行catch块代码,不执行catch后代码,程序中断执行
-
注意:
- 出现异常后,java会生成相应的异常对象,系统寻找匹配的catch块,找到后将异常对象赋给catch块异常参数
- 出现异常后,try块中尚未执行的语句不会执行
- 出现异常并处理后,catch块后面的语句还会执行
-
catch块处理异常:
- 调用异常对象的方法输出异常信息
- toString()方法,显示异常的类名和产生异常的原因
- void printStackTrace():输出异常的堆栈信息
- String getMessage():返回异常信息描述字符串,printStackTrace信息的一部分
- 继续向上抛出异常:throw e
- catch后的语句不执行:
- throw e
- 发生异常和catch中一场类型不匹配
- return
- 调用异常对象的方法输出异常信息
- finally语句
- 不管什么情况下,语句都会执行,使用finally
- return和finally语句的执行顺序:执行return之前的语句–执行finally语句–执行return
- finally在实际开发中的使用场合:IO流的管理,数据库连接的关闭,socket的关闭
- 唯一例外:System.exit(0); 终止当前正在运行的java虚拟机
2. 异常
2.1. 异常体系
Exception:所有异常类的父类,其子类对应了各种可能出现的异常事件
Exception分类:
- 运行时异常:Runtime Exception(unchecked Exception):可不必对其处理,系统会自动检测。
- 检查异常:Checked Exception:必须捕获进行处理,否则会出现编译错误。
public class TestException1 {
public static void main(String[] args) {
// 运行时异常,可不捕获,运行时才会发生异常
String str = "wyb";
System.out.println(str.toUpperCase());
NullPointerException ne;
ArithmeticException ae;
InputMismatchException ime;
ClassCastException cce;
int result = 10/0;
// 检查异常checked Exception
try {
Class.forName("com.wyb.cool").newInstance();
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
try {
InputStream is = new FileInputStream("c:wyb.txt");
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
}
}
}
2.2. 异常处理:throw、throws
- 手动抛出异常
- 在捕获一个异常前,必须有一段代码先生成异常对象并抛出。调用的就是throw子句
- 注意抛出运行时异常和Checked异常的区别
- 抛出Checked异常,该throw语句要么处于try块中,要么方法签名中有throws抛出
- 抛出运行时异常时,没有要求
- 声明异常throws
- 当Checked Exception产生时,不一定立刻处理,可以再把异常throws出
- 如果一个方法抛出多个已检查的异常,必须在方法的首部列出所有异常,之间用逗号分隔
- 子类声明的异常范围不能超过父类声明的范围:父类没有声明异常,子类也不能;不可抛出原有方法抛出异常类的父类或上层类
public class TestException2 {
public static void getAvg() throws Exception {
try {
Scanner input = new Scanner(System.in);
System.out.println("请输入总分");
int sum = input.nextInt();
System.out.println("请输入人数");
int count = input.nextInt();
if(count < 0) {
throw new Exception("人数不能是负数:" + count);
}
int result = sum / count;
System.out.println("result: " + result);
}catch (ArithmeticException e) {
e.printStackTrace();
}catch (NumberFormatException e) {
e.printStackTrace();
}catch (Exception e) {
e.printStackTrace();
throw e;
}finally {
System.out.println("finally");
}
System.out.println("bye");
}
public static void main(String[] args) throws Exception {
try{
getAvg();
}catch (Exception e) {
e.printStackTrace();
}
getAvg();
}
}
2.3. 自定义异常
创建自己的异常类,从Exception类或他的子类派生一个子类即可。习惯上,定义的类应该包含默认构造器和带有详细信息的构造器
public class AgeException extends RuntimeException{
public AgeException() {
}
public AgeException(String message) {
super(message);
}
}