Java 异常 异常链

一、异常

在程序运行过程中,会发生各种非正常的状况,比如程序运行时空间不足,网路连接中断,被装载的类不存在等,针对这种情况,在Java中引入了异常,以异常类的i形式对这些非正常情况进行封装,通过异常处理机制对程序运行时发生的各种问题进行处理。

二、异常处理

1、try....catch

try代码块中编写可能发生异常的Java语句,catch代码块中编写针对异常进行处理的代码,当try代码块中的程序发生了异常,系统会将这个异常的信息封装成一个异常对象,并将这个对象传给catch代码块。catch代码块需要一个参数指明它所能够接受的异常类型,这个参数的类型必须是Exception类或其子类。

如接下来的代码:

public class Example {
     //实现了两个整数相除的方法
	public static int divide(int x, int y) { 
		int result = x / y;        
		return result;   
	}
	public static void main(String[] args) {
         //定义一个try…catch语句用于捕获异常
		try {                                      
			int result = divide(4, 0);    //调用divide()方法
			System.out.println(result);   
		} catch (Exception e) {            //对异常进行处理
			System.out.println("捕获的异常信息为:" + e.getMessage());
		}
		System.out.println("程序继续向下执行...");
	}
 }
结果:


如果没有try....catch的结果


可以看到使用try....catch后,可以返回异常信息,更便于找到错误信息。

注意:

①try代码块中,发生异常语句后面的代码是不会被执行的。如下面这句话没有执行

   System.out.println(result);   

②在catch代码块对异常处理完毕后,程序仍会向下执行。如下面这句话执行了

System.out.println("程序继续向下执行...");


2、finally:

有时候我们希望有些语句无论是否发生异常都要执行,这时就可以在try....catch后,加一个finally代码块。即使发生异常,catch语句中有return语句结束程序,finally里的语句仍然可以执行。如下面代码

public class Example2 {
	public static void main(String[] args) {
          //定义try…catch…finally语句用于捕获异常
		try {
			int result = divide(4, 0);       //调用divide()方法
			System.out.println(result);
		} catch (Exception e) {               //对捕获到的异常进行处理
			System.out.println("捕获的异常信息为:" + e.getMessage());
              return;                             //用于结束当前语句
		} finally {                             
			System.out.println("即使catch语句中return这条语句仍会");
		}
          System.out.println("程序继续向下执行…");
	}
     //下面的方法实现了两个整数相除
	public static int divide(int x, int y) {
		int result = x / y;                  //定义一个变量result记录两个数相除的结果
		return result;                        //将结果返回
	}
}

结果

捕获的异常信息为:/ by zero

即使catch语句中return这条语句仍会

可以看到使用finally后,即使catch语句中return语句,finally里的语句仍会执行。


3、throws关键字

①在定义一个方法时可以使用throws关键字声明,使用throws声明的方法表示此方法不处理异常,而是交给方法的调用处进行处理。

但管是否会产生异常,在调用方法处都必须进行异常处理。

若没有异常处理,编译错误,如下面代码(即使没有错误,但因没有异常处理,就错了)

public class Example {
	public static void main(String[] args) {
		int result = divide(4, 2);    //调用divide()方法,这里没有异常处理,错了
		System.out.println(result);
	}
     //实现两个整数相除,并使用throws关键字声明抛出异常
	public static int divide(int x, int y) throws Exception {
		int result = x / y;           //定义一个变量result记录两个数相除的结果
		return result;                 //将结果返回
	}
}
若加上异常处理,就对了,哈哈,如下面代码

public class Example {
	public static void main(String[] args) {
         //下面的代码定义了一个try…catch语句用于捕获异常
		try {
			int result = divide(4, 2);   //调用divide()方法
			System.out.println(result); 
		} catch (Exception e) {           //对捕获到的异常进行处理
			e.printStackTrace();          //打印捕获的异常信息
		}
	}
     //下面的方法实现了两个整数相除,并使用throws关键字声明抛出异常
	public static int divide(int x, int y) throws Exception {
		int result = x / y;      //定义一个变量result记录两个数相除的结果
		return result;            //将结果返回
	}
}
结果:



②在上例中,当调用divide()方法时,如果不知道如何处理声明抛出的异常,也也可以使用throws关键字继续抛出异常,如下代码

public class Example2 {
	public static void main(String[] args)throws Exception {
		int result = divide(4, 0);   // 调用divide()方法
		System.out.println(result);
	}
    // 下面的方法实现了两个整数相除,并使用throws关键字声明抛出异常
	public static int divide(int x, int y) throws Exception {
		int result = x / y;          // 定义一个变量result记录两个数相除的结果
		return result;                // 将结果返回
	}
}
结果:
Exception in thread "main" java.lang.ArithmeticException: / by zero
at pocket1.Example2.divide(Example2.java:10)
at pocket1.Example2.main(Example2.java:5)


③在上面的代码中,不管是否有问题都要使用try...catch块进行异常处理,throws在主方法中也是可以使用throws关键字,但是主方法是程序的起点,所以此时主方法再向上抛异常,则只能抛给JVM进行处理,我们就可以使用try...catch块进行异常处理,如下代码

public class Example2 {
	public static void main(String[] args)throws Exception {
	     int result = divide(4, 2);   // 调用divide()方法
	     System.out.println(result);
	}
	    // 下面的方法实现了两个整数相除,并使用throws关键字声明抛出异常
	public static int divide(int x, int y) {
	     int result = x / y;          // 定义一个变量result记录两个数相除的结果
	     return result;                // 将结果返回
	}
}
结果:2


4、自定义异常

虽然Java中定义了大量的异常类,可以描述编程时出现的大部分异常情况,但是再程序开发中有时可能需要描述程序中特有的情况。例如在设计divide()方法时,不允许被除

数为负数,为解决这个问题,在Java中允许用户自定义异常。

自定义的异常必须继承字Exception或其子类。如下面代码

class DivideByMinusException extends Exception{
	public DivideByMinusException (){
		super();          // 调用Exception无参的构造方法
	}
	public DivideByMinusException (String message){
		super(message); // 调用Exception有参的构造方法
	}
}

public class Example2 {
	public static void main(String[] args) {
              // 下面的代码定义了一个try…catch语句用于捕获异常
		try {
			int result = divide(4, -2);  // 调用divide()方法,传入一个负数作为被除数
			System.out.println(result);
		} catch (DivideByMinusException e) {     // 对捕获到的异常进行处理
			System.out.println(e.getMessage()); // 打印捕获的异常信息
		}
	}
    // 下面的方法实现了两个整数相除,并使用throws关键字声明抛出自定义异常
	public static int divide(int x, int y) throws DivideByMinusException {
		if (y < 0) {
			throw new DivideByMinusException("被除数是负数");// 使用throw关键字声明异常对象
		}
		int result = x / y;     // 定义一个变量result记录两个数相除的结果
		return result;           // 将结果返回
	}
}

结果:被除数是负数


5、Java中的异常链

package tcy01;

public class ChainTest{
	/*
	 *test1():抛出异常 
	 *test2():调用test1(),捕获test1()抛出的异常,并且包装成运行时异常,继续抛出 
	 *main方法中,调用test2(),尝试test2()方法抛出的异常。 
   */
	public static void main(String[] args){//main方法调用test2(),尝试test2()方法抛出的异常。
		ChainTest ct=new ChainTest();
		try{
			ct.test2();
		}catch(Exception e){
			e.printStackTrace();
		}
	}
	
	public void test1() throws DefineException{
		throw new DefineException("test1()抛出的异常");
	}
	public void test2(){ //test2()调用test1(),捕获test1()抛出的异常
		try{
			test1();
		}catch(DefineException e){
		    RuntimeException newExc=new RuntimeException("test2()中抛出的异常");
		    newExc.initCause(e); //包装成运行时异常
		    throw newExc; //继续抛出异常 
		}
	}
}

结果:

java.lang.RuntimeException: test2()中抛出的异常
at tcy01.ChainTest.test2(ChainTest.java:25)
at tcy01.ChainTest.main(ChainTest.java:12)
Caused by: tcy01.DefineException: test1()抛出的异常
at tcy01.ChainTest.test1(ChainTest.java:19)
at tcy01.ChainTest.test2(ChainTest.java:23)
... 1 more

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值