异常与捕获
- 几乎所有的代码里面都会出现异常,为了保证程序在出现异常之后可以正常执行完毕,就需要进行异常处理。
- 先来看一下异常的继承类结构:
在java中异常也是类。(一切皆对象)
异常类继承关系:只有Throwable以及其子类能够进行异常捕获和处理。
- Error:描述JVM运行时内部错误,如栈溢出,堆溢出。
- Exception:程序中普遍存在的,由于代码问题产生的错误。
-----IOException:由于输入输出产生的异常,如在程序中打开了一个并不存在的文件。
-----RuntimeException:(编译不出错,一运行就出错)发生在运行时异常,如数组越界异常,类型转换异常,空指针异常(NPE)
受查异常:除了非受查异常的所有异常类都属于受查异常,强制用户进行异常处理。
非受查异常:Error、RuntimeException及其子类。不强制用户进行异常处理。
异常的影响
异常是导致程序中断执行的一种指令流。程序之中如果出现异常并且没有合理处理的话就会导致程序终止执行。
范例:产生异常
package test;
public class Test {
public static void main(String[] args) {
System.out.println("1.数学计算开始前");
System.out.println("2.进行数学计算:"+10/0);
System.out.println("3.数学计算结束后");
}
}
1.数学计算开始前 Exception in thread"main"java.lang.ArithmeticException
现在程序之中产生了异常,但是在异常语句产生之前的语句可以正常执行完毕,而异常产生之后程序直接进行了结束。为了保证程序出现异常后还可以继续向下执行,就需要异常处理。
异常处理格式
异常处理的语法格式如下:
try{
有可能出现异常的语句 ;
}[catch (异常类 对象) {
} ... ]
[finally {
异常的出口
}]
try
[catch....]
[catch.....]
...
[finally]
可以出现的组合:
try..[1..N]catch..
try..finally..
try..[1..N]catch...finally..
try:所有可能出现异常的代码。
catch:当相应异常出现时,捕获该异常,然后自定义处理方式。
finally:保证重点代码(如 IO流的关闭,JDBC资源的释放等)一定会被执行的机制,无论是否产生异常,finally代码块中的内容一定会被执行。
package test;
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.数学计算结束后");
}
}
出现了异常之后,由于存在异常处理机制,依然可以正常执行完毕。
以上代码虽然进行了异常处理,但是存在一个问题:你现在根本不知道程序产生了什么样的异常。所以为了明确的取得异常信息,可以直接输出异常类对象,或者调用所有异常类中提供的printStackTrace()方法进行完整异常信息的输出。
范例:取得异常的完整信息
package test;
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 进行处理。
范例:使用 try…catch…finally 进行处理
package test;
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会作为程序统一出口。
throws关键字
在进行方法定义的时候,如果要告诉调用者本方法可能产生哪些异常,就可以使用throws方法进行声明。即如果该方法出现问题后不希望进行处理,就使用throws抛出。
thorws用在方法上
范例:使用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 ;
}
}
如果现在调用了throws声明的方法,那么在调用时必须明确的使用try…catch…进行捕获,因为该方法有可能产生异常,所以必须按照异常的方式来进行处理。
主方法本身也属于一个方法,所以主方法上也可以使用throws进行异常抛出,这个时候如果产生了异常就会交给JVM处理。
范例:主方法抛出异常
package test;
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关键字
thorw是直接编写在语句之中,表示人为进行异常的抛出。如果现在异常类对象实例化不希望由JVM产生而由用户产生,就可以使用throw来完成throw用在方法中
范例:使用throw产生异常类对象。
public static void main(String[] args){
try {
throw new Exception("抛个异常玩玩") ;
} catch (Exception e) {
e.printStackTrace();
}
}
请解释throw和throws的区别:
- throw用于方法内部,主要表示手工异常抛出。
- throws主要在方法声明上使用,明确告诉用户本方法可能产生的异常,同时该方法可能不处理此异常。
自定义异常类
在Java里,针对于可能出现的公共的程序问题都会提供有相应的异常信息,但是很多时候这些异常信息往往不够我们使用。
例如,现在有需求:在进行加法运算时,如果发现两个数相加内容为50,那么就应当抛出一个AddException异常。这种异常Java不会提供,所以就必须定义一个属于自己的异常类。
自定义异常类可以继承两种父类:Exception、RuntimeException。
范例:实现自定义异常类
class AddException extends RuntimeException{
public AddException(String msg){
super (msg);
}
}
public class Test {
public static void main(String[] args) {
int a = 1;
int b = 1;
int c = a + b;
if (c == 2){
throw new AddException("此时1+1不能等于2!");
}
}
}
在项目的系统设计或者架构设计时,一定会涉及到与业务相关的异常问题,此时需要自定义异常类。