异常
1、什么是异常
例如除数不能为0,否则报错
2、try…catch 和finally
为了解决异常,java提供对异常进行处理的方式,异常捕获。使用try…catch语句实现
try{
//程序代码块
}catch (Exception e){ //Exception类或其子类
//对ExceptionType的处理
}
说明:在try中放可能出现异常的语句,在catch中放针对异常进行处理的代码。
package review;
//1.接口
interface Animal{
void shout();
}
public class r1 {
public static void main(String[] args) {
try{
int re = divide(4,0);
System.out.println(re);
} catch(Exception e){ //参数是Exception类
System.out.println("捕获的异常信息:"+e.getMessage());
}
System.out.println("程序继续向下执行");
}
public static int divide(int x , int y){
int r = x / y;
return r;
}
}
捕获的异常信息:/ by zero
程序继续向下执行
发生异常语句后面的代码不会被执行。
如果希望有些语句无论程序是否发生异常都要执行,这时需要在try…catch语句后面加一个finally代码块。
package review;
//1.接口
interface Animal{
void shout();
}
public class r1 {
public static void main(String[] args) {
try{
int re = divide(4,0);
System.out.println(re);
} catch(Exception e){ //参数是Exception类
System.out.println("捕获的异常信息:"+e.getMessage());
return;//程序结束,后面除过finally代码块中的语句,其他语句都不会被执行
} finally {
System.out.println("finally代码块");//finally代码块无论程序提前结束都会执行
}
System.out.println("程序继续向下执行");//程序结束不执行
}
public static int divide(int x , int y){
int r = x / y;
return r;
}
}
捕获的异常信息:/ by zero
finally代码块
finally代码块无论程序提前结束都会执行,不受return影响。
但受System.exit(0);因为该语句表示退出java虚拟机,任何代码都运行不了。
3、throws关键字
在方法的后面使用throws关键字对外声明该方法有可能发生的异常,从而检查方法中是否存在异常。
throws关键字声明抛出异常的语法格式:
修饰符 返回类型 方法名(参数表) throws 异常类1 , 异常类2...{
//方法体
}
public static void main(String[] args){
int re = divide(4 , 2);
System.out.println(re);
}
//使用throws声明抛出异常
public static int divide(int x , int y) throws Exception {
int r = x / y;
return r;
}
//未报告的异常错误java.lang.Exception; 必须对其进行捕获或声明以便抛出
在前面调用divide方法时,就出现了抛出异常,不能除0的异常,所以程序直接不能编译,报错。
说明divide 方法存在错误。
最终导致程序不能正常运行,计算4/2
若要程序还能够继续运行,方法:
(1)用try…catch处理divide方法抛出的异常
package review;
public class r1 {
public static void main(String[] args) {
try{
int re = divide(4,2);
System.out.println(re);
} catch(Exception e){
e.printStackTrace(); //打印捕获的异常信息
}
}
public static int divide(int x , int y) throws Exception {
int r = x / y;
return r;
}
}
2
(2)若不会try…catch将异常抛出,也可以使用throws关键字继续将异常抛出。
给调用方法的方法中加throws,如在main中加
package review;
public class r1 {
public static void main(String[] args) throws Exception {
int re = divide(4,2);
System.out.println(re);
}
public static int divide(int x , int y) throws Exception {
int r = x / y;
return r;
}
}
2
4、编译时异常与运行时异常
在程序编译时产生的异常,必须对这些异常进行处理,这种异常称为编译时异常,也称checked异常。
在运行时产生的,不编写异常处理代码依然可以通过编译,称为运行时异常,也称unchecked异常。
(1)编译时异常
在Exception类中,除RuntimeException类及其子类外,Exception的其他子类都是编译时异常。
出现异常后必须对异常进行处理,否则不会编译。
处理方法为:try…catch对异常进行捕获处理;throws关键字声明抛出异常,调用者对异常进行处理。
(2)运行时异常
RuntimeException类及其子类都是运行时异常。
编译器不会对该类异常进行检查,换句话说,就是当程序中出现这类异常时,即使没有使用try…catch语句捕获或使用throws声明抛出异常,程序也能编译通过。
如,数组越界,就会发生运行异常,仍会编译通过。
int[] arr = new int[5];
System.out.println(arr[6]);
5、自定义异常
java允许用户自定义异常,但自定义的异常类必须继承自Exception或其子类。
自定义异常:
//1.自定义异常继承Exception
class Divide extends Exception{
public Divide(){
super(); //调用Exception的构造方法
}
public Divide(String message){
super(message);
}
}
(1)自定义异常中使用throw关键字在方法中声明异常的实例对象:(而非throws)
throw Exception 异常对象
(2)使用throw关键字在方法中向调用者抛出自定义的Divide异常对象:
package review;
//1.自定义异常继承Exception
class Divide extends Exception{
public Divide(){
super(); //调用Exception的构造方法
}
public Divide(String message){
super(message);
}
}
public class r1 {
public static void main(String[] args) throws Exception {
int re = divide(4,-2);//不允许被除数是负数,否则出现异常
System.out.println(re);
}
public static int divide(int x , int y) {
if(y < 0){
throw new Divide("除数是负数");//标红,报错,编译不通过
}
int r = x / y;
return r;
}
}
为什么不会编译通过?
是因为在一个方法内使用throw关键字抛出异常对象时,必须要使用try…catch语句对抛出的异常进行处理,或者在divide()方法上,使用throws关键字声明抛出异常,从而,程序正常编译。
package review;
//1.自定义异常继承Exception
class Divide extends Exception{
public Divide(){
super(); //调用Exception的构造方法
}
public Divide(String message){
super(message);
}
}
public class r1 {
public static void main(String[] args) throws Exception {
//2.定义try...catch语句用于捕获异常
try {
int re = divide(4, -2);//不允许被除数是负数,否则出现异常
System.out.println(re);
} catch (Divide e){ //利用自定义的异常,对捕获到的异常进行处理
System.out.println(e.getMessage()); //打印捕获到的异常信息
}
}
//3.使用throws关键字声明抛出自定义异常
public static int divide(int x , int y) throws Divide{
if(y < 0){
throw new Divide("除数是负数");
}
int r = x / y;
return r;
}
}
在调用divide()方法时,传入的除数不能为负数,否则程序会抛出一个自定义的Divide异常,该异常最终被catch代码块捕获处理,并打印异常信息。
程序运行顺序:
调用divide(4, -2) --> throw new Divide()抛出一个异常 --> 跳转到catch处理异常 --> 打印异常信息 --> 程序正常结束。
总之:
(1) 当发生异常时,程序会立即终止,不会向下继续执行,为了就是解决异常,使程序能捕获到异常并打印异常信息,在发生异常后,然后程序不会停止,继续执行,
为了这个目标引进了异常捕获和异常处理,即try…catch语句。
(2)使用throws关键字,来抛出方法中所存在的异常,如果该方法存在异常,则在调用方法时标红报错,
要想解决这个问题,不让报错,想让程序能正常编译运行,有两个方法,一是try…catch捕获异常处理异常(方法调用放在try中),二是在方法调用所在的方法中同样用throws Exception抛出异常。
(3)自定义异常,只是继承Exception派生新的异常类,
使用throw关键字声明异常的实例对象,将该对象放在要发生异常的代码块中,用来判断是否发生异常,
其余异常处理,抛出异常类似于前面,注意在catch声明异常类。