Java的异常处理主要通过try,catch,finally,throw,throws五个关键字。
Java把异常当作对象来处理,并定义一个基类java.lang.Throwable作为所有异常的超类。在Java API中已经定义了许多异常类,这些异常类分为两大类,错误Error和异常Exception,Java异常体系结构呈树状,如下
下面举个异常类常见使用,eg
- public class TestDiv
- {
- public static void main(String[] args)
- {
- try
- {
- int a = Integer.parseInt(args[0]);
- int b = Integer.parseInt(args[1]);
- int c = a / b;
- System.out.println("您输入的两个数相除的结果是:" + a / b);
- }
- catch (IndexOutOfBoundsException ie)
- {
- System.out.println("数组越界:运行程序时输入的参数个数不够");
- }
- catch (NumberFormatException ne)
- {
- System.out.println("数字格式异常:程序只能接受整数参数");
- }
- catch (ArithmeticException ae)
- {
- System.out.println("算术异常");
- }
- catch (Exception e)
- {
- e.printStackTrace();
- System.out.println("未知异常");
- }
- }
- }
这里要注意:一定要先捕获小的异常
finally主要用在回收写物理资源(网络连接,数据库连接,文件连接等),eg
- public class TestFinally
- {
- public static void main(String[] args)
- {
- FileInputStream fis = null;
- try
- {
- fis = new FileInputStream("a.txt");
- }
- catch (IOException ioe)
- {
- System.out.println(ioe.getMessage());
- //return语句强制方法返回
- //return ;
- //使用exit来退出虚拟机
- System.exit(1);
- }
- finally
- {
- //关闭磁盘文件,回收资源
- if (fis != null)
- {
- try
- {
- fis.close();
- }
- catch (IOException ioe)
- {
- ioe.printStackTrace();
- }
- }
- System.out.println("程序已经执行了finally里的资源回收!");
- }
- }
- }
这里要注意:finally中不要使用return或throw,因为这会使try,catch中的return或throw失效
java独特的提供了checked异常这使一些问题能在编译时就解决。
下面再举throw和throws的例子,eg
- public class TestThrow
- {
- public static void main(String[] args)
- {
- try
- {
- //调用带throws声明的方法,必须显式捕获该异常
- //否则,必须在main方法中再次声明抛出
- throwChecked(-3);
- }
- catch (Exception e)
- {
- System.out.println(e.getMessage());
- }
- //调用抛出Runtime异常的方法既可以显式捕获该异常,
- //也可不理会该异常
- throwRuntime(3);
- }
- public static void throwChecked(int a)throws Exception
- {
- if (a > 0)
- {
- //自行抛出Exception异常
- //该代码必须处于try块里,或处于带throws声明的方法中
- throw new Exception("a的值大于0,不符合要求");
- }
- }
- public static void throwRuntime(int a)
- {
- if (a > 0)
- {
- //自行抛出RuntimeException异常,既可以显式捕获该异常
- //也可完全不理会该异常,把该异常交给该方法调用者处理
- throw new RuntimeException("a的值大于0,不符合要求");
- }
- }
- }
然后我简单讲下,自定义异常类,其实只要继承另外的异常类,实现2个构造方法,eg
- public class AuctionException extends Exception
- {
- //异常类无参数的构造器
- public AuctionException(){}
- //带一个字符串参数的构造器
- public AuctionException(String msg)
- {
- super(msg);
- }
- }
利用catch和throw同时使用形成异常链,eg
- public class TestAuction
- {
- private double initPrice = 30.0;
- public void bid(String bidPrice)
- throws AuctionException
- {
- double d = 0.0;
- try
- {
- d = Double.parseDouble(bidPrice);
- }
- catch (Exception e)
- {
- //此处完成本方法中可以对异常执行的修复处理,此处仅仅是在控制台打印异常跟踪信息。
- e.printStackTrace();
- //再次抛出自定义异常
- throw new AuctionException("竞拍价必须是数值,不能包含其他字符!");
- }
- if (initPrice > d)
- {
- throw new AuctionException("竞拍价比起拍价低,不允许竞拍!");
- }
- initPrice = d;
- }
- public static void main(String[] args)
- {
- TestAuction ta = new TestAuction();
- try
- {
- ta.bid("df");
- }
- catch (AuctionException ae)
- {
- //main方法再次捕捉到bid方法中的异常。并对该异常进行处理
- System.err.println(ae.getMessage());
- }
- }
- }
这样异常越来越精确,便于调试,纠错。
异常跟踪栈(printStackTrace这方法就是打出的)这是为了方便你找到异常的源头。使用IDE的人调试时都离不开它。
下面举两个典型例子,大家随便加点断点,单步走走,看看堆栈,一定收获颇丰,eg
- class SelfException extends Exception
- {
- SelfException(){}
- SelfException(String msg)
- {
- super(msg);
- }
- }
- public class TestPrintStackTrace
- {
- public static void main(String[] args)throws SelfException
- {
- firstMethod();
- }
- public static void firstMethod()throws SelfException
- {
- secondMethod();
- }
- public static void secondMethod()throws SelfException
- {
- thirdMethod();
- }
- public static void thirdMethod()throws SelfException
- {
- throw new SelfException("自定义异常信息");
- }
- }
下面这个例子加强你的多线程的调试能力
- public class TestThreadException implements Runnable
- {
- public void run()
- {
- firstMethod();
- }
- public void firstMethod()
- {
- secondMethod();
- }
- public void secondMethod()
- {
- int a = 5;
- int b = 0;
- int c = a / b;
- }
- public static void main(String[] args)
- {
- new Thread(new TestThreadException()).start();
- }
- }
最后警告句:
能自己处理的异常就自己处理掉,抛出异常系统开销很大,try..catch的范围越小越好,大家不要偷懒,不然不容易发现问题。能自己处理的异常就自己处理掉,抛出异常系统开销很大,try..catch的范围越小越好,大家不要偷懒,不然不容易发现问题。
能自己处理的异常就自己处理掉,抛出异常系统开销很大,try..catch的范围越小越好,大家不要偷懒,不然不容易发现问题。