Java异常与捕获
几乎所有的代码里面都会出现异常,为了保证程序在出现异常之后可以正常执行完毕,就需要进行异常处理。
先来看一下异常的继承类结构:
在Exception之下又分为两个分支,RuntimeException和IOException。
由于程序错误导致的异常属于RuntimeException;而如果程序本身没有问题,但由于像I/O错误这类问题导致的异常
属于IOException。
1.RuntimeException(运行时异常):由于程序错误导致的异常。
2.IOException : 程序本身没有问题,但由于出现I/O问题导致的异常(例如:打开一个并不存在的文件)
3.非受查异常: 继承与Error与RuntimeException类的所有异常子类称为非受查异常(不强制用户进行异常处理)
4.受查异常: Exception以及IOException子类属于受查异常(强制用户进行异常处理)
5.Error (栈溢出异常): Error类描述Java运行时内部错误与资源耗尽错误。应用程序不抛出此类异常,这种内部错误一旦出现,除了告知用户并使程序安全终止之外,别无他法。
一、异常处理格式
为了保证程序出现异常后也能正常执行下去,需要进行异常处理。
语法如下:
try{
//有可能出现异常的语句
} [catch( 异常类 对象 )......] {
//出现异常后的解决方案
} [finally] {
//异常出口,无论是否产生异常,均会执行finally代码块
//即便try,catch中存在return语句,也会在return之前执行finally代码块
}
try...catch...
try...finally...
try...catch...finally...
快捷键:ctrl +alt +t
1、对异常进行处理
public class Test {
public static void main(String[] args) {
System.out.println("1.数学计算开始前");
try {
System.out.println("2.进行数学计算:"+10/0);
} catch (ArithmeticException e) {
System.out.println("异常已经被处理了");
}
System.out.println("3.数学计算结束后");
}
}
2、取得异常的完整信息
public class Test {
public static void main(String[] args) {
System.out.println("1.数学计算开始前");
try {
System.out.println("2.进行数学计算:"+10/0);
} catch (ArithmeticException e) {
e.printStackTrace();
}
System.out.println("3.数学计算结束后");
}
}
在进行异常处理的时候还可以使用try…catch…finally进行处理。
3、使用try…catch…finally进行处理
public class Test {
public static void main(String[] args) {
System.out.println("[1].数学计算开始前");
try {
System.out.println("[2].进行数学计算:"+10/0);
} catch (ArithmeticException e) {
e.printStackTrace();
}finally {
System.out.println("[Finally]不管是否产生异常,都执行此语句");
}
System.out.println("[3].数学计算结束后");
}
}
不管此时是否产生异常,最终都要执行finally程序代码,所以finally会作为程序统一出口。
4、初始化参数进行数学运算
public class Test {
public static void main(String[] args) {
System.out.println("[1].数学计算开始前");
try {
int x = Integer.parseInt(args[0]) ;
int y = Integer.parseInt(args[1]) ;
System.out.println("[2].进行数学计算:"+x/y);
} catch (ArithmeticException e) {
e.printStackTrace();
}finally {
System.out.println("[Finally]不管是否产生异常,都执行此语句");
}
System.out.println("[3].数学计算结束后");
}
}
此时会存在如下问题:
用户没有输入初始化参数:ArrayIndexOutOfBoundsException
用户输入的不是数字:NumberFormatException
被除数为0:ArithmeticExceptio
以上代码我们发现,通过catch捕获异常的时候如果没有捕获指定异常,程序依然无法进行处理,现在最直白的解决
方法就使用多个catch。
5、多个catch块
public class Test {
public static void main(String[] args) {
System.out.println("[1].数学计算开始前");
try {
int x = Integer.parseInt(args[0]) ;
int y = Integer.parseInt(args[1]) ;
System.out.println("[2].进行数学计算:"+x/y);
}catch (ArithmeticException e) {
e.printStackTrace();
}
catch (NumberFormatException e) {
e.printStackTrace();
}
catch (ArrayIndexOutOfBoundsException e) {
e.printStackTrace();
}finally {
System.out.println("[Finally]不管是否产生异常,都执行此语句");
}
System.out.println("[3].数学计算结束后");
}
}
二、 throws关键字
throws —用在方法上,明确表示此方法可能会产生异常但是方法内部不处理,将异常抛回给调用处。
1、使用throws定义方法
package test;
public class Test {
public static void main(String[] args) {
try {
System.out.println(calculate(10, 0));
} catch (Exception e) {
e.printStackTrace();
}
}
public static int calculate(int x,int y) throws Exception {
return x/y ;
}
}
2、主方法抛出异常
public class Test {
public static void main(String[] args) throws Exception{
System.out.println(calculate(10, 0));
}
public static int calculate(int x,int y) throws Exception {
return x/y ;
}
}
三、throw关键字
throw —用在方法中。由用户产生异常类对象。一般与自定义异常搭配使用。
1、使用throw产生异常类对象。
public static void main(String[] args){
try {
throw new Exception("抛个异常玩玩") ;
} catch (Exception e) {
e.printStackTrace();
}
}
面试题:请解释throw和throws的区别
- throw用于方法内部,主要表示手工异常抛出。
- throws主要在方法声明上使用,明确告诉用户本方法可能产生的异常,同时该方法可能不处理此异常。
2.异常处理标准的格式
举一个例子:
现在要求编写一个方法进行除法操作,但是对于此方法有如下要求:
- 在进行除法计算操作之前打印一行语句"**".
- 如果在除法计算过程中出现错误,则应该将异常返回给调用处。
- 不管最终是否有异常产生,都要求打印一行计算结果信息。
public class Test {
public static void main(String[] args){
try {
System.out.println(calculate(10, 0));
} catch (Exception e) {
e.printStackTrace();
}
}
public static int calculate(int x,int y) throws Exception {
int result = 0 ;
System.out.println("1.[计算开始前]*****");
try {
result = x / y ;
} catch (Exception e) {
throw e ; // 抛出去
} finally {
System.out.println("2.[计算结束]#####");
}
return result ;
}
}
用try…finally的格式:
public static int calculate(int x,int y) throws Exception {
int result = 0 ;
System.out.println("1.[计算开始前]*****");
try {
result = x / y ;
}finally {
System.out.println("2.[计算结束]#####");
}
return result ;
}
面试题:请解释Exception与RuntimeException的区别,请列举几个常见的RuntimeException:
- 使用Exception是RuntimeException的父类,使用Exception定义的异常都要求必须使用异常处理,而使用 RuntimeException定义的异常可以由用户选择性的来进行异常处理。
- 常见的RuntimeException:ClassCastException、NullPointerException等。
3.自定义实现异常类
自定义异常类可以继承两种父类:Exception、RuntimeException。
class AddException extends Exception{
public AddException(String msg){
super(msg);
}
}
public class Test{
public static void main(String[] args) throws Exception{
int n = 10;
int m = 20;
if(n+m==30){
throw new AddException("错误的相加操作");
}
}
}