欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

throws & throw & 自定义异常

程序员文章站 2022-07-14 10:26:44
...

我们知道当程序遇到异常时除了用try-catch-finally来捕获异常外,还可以用throws和throw去抛出异常,使用异常处理可以定位问题所在处,方便修改程序代码:

例如利用try-catch-finally来捕获异常:

public class Test{

	public static void main(String[] args) {	
		try {
			System.out.println(1/0);
		} catch (Exception e) {
			e.printStackTrace();//输出异常
		}
	}
}
输出结果:
java.lang.ArithmeticException: / by zero
	at com.jd.pao.Test.main(Test.java:8)

还可以使用throw关键字来抛出异常:

public class Test{

	public static void main(String[] args) {	
		throw new NullPointException("抛出一个空指针异常");
	}
}
输出结果:
Exception in thread "main" java.lang.NullPointerException
	at com.jd.pao.Test.main(Test.java:7)

上述两种异常ArithmeticException(算数异常)、NullPointException(空指针异常)都属于RuntimeException(运行时异常),运行时异常比较容易掌握,检查时异常就需要用心记住了,它较运行时异常有点复杂,不过在详述检查时异常之前,我们首先要知道:一个异常如果直接或间接继承RuntimeException,该异常就属于运行时异常;如果是继承Exception,则该异常属于检查时异常,这两句话在自定义异常中也非常重要,例如:

用throw抛出一个由检查时异常创建的对象时有两种处理方式:
第一种是在方法参数列表括号的后面加上throws 异常类

public class Test {

	public static void main(String[] args) throws Exception {	
		throw new Exception("抛出一个检查时异常");
	}
}
输出结果:
Exception in thread "main" java.lang.Exception: 抛出一个检查时异常
	at com.jd.pao.Test.main(Test.java:7)

另一种是用try-catch-finally来捕获检查时异常:

public class Test {

	public static void main(String[] args){	
		try {
			throw new Exception("用try-catch来捕获一个检查时异常");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
输出结果:
java.lang.Exception:try-catch来捕获一个检查时异常
	at com.jd.pao.Test.main(Test.java:8)

这两种方式有区别:
当使用throws时是将错误抛给别人,异常下面的代码不执行而使用try-catch-finally时是将错误抛给自己,异常下面的代码也会执行(笔者是这样记的,将错误抛给自己,自己选的路,死活也要走完),且要记住throw下面不能直接跟代码(就如return下面不能直接写代码一样),例如:

public class Test{

	public static void main(String[] args) throws Exception{
		
		if(true) {
			throw new Exception("此处用throws去抛出异常,所以下满代码不能执行");//后面不能直接写代码,否则报错
		}
		System.out.println("我就不执行");
	}
}
输出结果:
Exception in thread "main" java.lang.Exception: 此处用throws去抛出异常,所以下满代码不能执行
	at com.jd.pao.Test.main(Test.java:9)

public class Test{

	public static void main(String[] args){
		
		try {
			throw new Exception("此处用try-catch来捕获一个检查时异常,下面代码会执行");
		} catch (Exception e) {
			e.printStackTrace();
		}		
		System.out.println("我要执行喽!");
	}
}
输出结果:
java.lang.Exception: 此处用try-catch来捕获一个检查时异常,下面代码会执行
我要执行喽!
	at com.jd.pao.Test.main(Test.java:8)

下面我们来结合上面说说自定义异常,我们会发现有时已有的异常类并不能完全阐明错误的具体类型,这时就要我们自己定义一个异常类来具体阐明问题的根本:
自定义异常类要继承已有的异常类,通常继承RuntimeException(执行时异常)和Exception(检查时异常),

public void Custom extends RuntimeException{
	public Custom (String s){
		super(s);
	}
}
public void Custom extends Exception{
	public Custom (String s){
		super(s);
	}
}

上述两种自定义类的使用规则就和上面讲的一样,要区分是继承RuntimeException还是Exception!

下面是一个练习,想看的可以看一下,不看了也无所谓:

package com.jd.pao;

public class Test {

	  public static void div(int a,int b) throws Exception{//使用try-catch默认有throws,为便于理解,此处显示出来
		  if(b==0) {
		      try {
		        throw new Exception("分母不能为0");//因为此处通过try-catch捕获了异常,
		      } catch (Exception e) {
		        System.out.println("分母为0时会执行");
		        e.printStackTrace();
		      }
		  }else{
		  		System.out.println(a/b);
		  }
	  }
		  
	  public static void main(String[] args) {
		  try {
			  div(1,0);//也就相当于此处已无异常,所以当此处执行完毕后,不会跳到catch代码块里
		  } catch (Exception e) {
			  System.out.println("永远不会执行");
		  }
	  }
}
输出结果:
分母为0时会执行
java.lang.Exception: 分母不能为0
	at com.jd.pao.Test.div(Test.java:8)
	at com.jd.pao.Test.main(Test.java:20)
package com.jd.pao;

public class Test {

	  public static void div(int a,int b) throws Exception{//此处必须要显式使用throws
		  if(b==0) {    
		      throw new Exception("分母不能为0");//因为此处将异常抛出,	     
		  }else {
			  System.out.println(a/b);
		  }
	  }
		  
	  public static void main(String[] args) {
		  try {
			  div(1,0);//所以此处会报错,出现异常,会跳到catch代码块里
		  } catch (Exception e) {
			  System.out.println("异常时会执行");
		  }
	  }
}
输出结果:
异常时会执行