zoukankan      html  css  js  c++  java
  • 异常——try、catch、finally、throw、throws

    异常(exception)就是程序在执行过程中发生的、破坏程序正常指令流的事件。

    异常是对象,对象都要用类来定义。异常的根类是java.lang.Throwable。

     异常分为三类:

    • 检查性异常(checked exception):

        不是修改程序能解决的问题。

        java语法规定:受检查异常,比如IO异常,SQL异常,必须向上声明抛出(使用throwrs关键字)或者处理掉否则无法通过编译。

        Java要求非运行异常必须函数抛出,让编译器帮助定位异常出现的代码段,并且必须使用try、catch块,否则编译都不会通过,所以也叫可检查异常。

        最具代表的检查性异常是用户错误或问题引起的异常,这是程序员无法预见的。

        例如要打开一个不存在文件时,一个异常就发生了,这些异常在编译时不能被简单地忽略。

        

        //既要声明(throws)也要抛出(throw),调用时用try、catch捕捉
        public void last() throws IOException{
            throw new IOException();
        }
    • 运行时异常(runtime exception):

        是程序写的有问题。

        运行时异常是可能被程序员避免的异常。

        与检查性异常相反,运行时异常可以在编译时被忽略。

    • 错误(error):

        错误不是异常,而是脱离程序员控制的问题。

        错误在代码中通常被忽略。

        例如,当栈溢出时,一个错误就发生了,它们在编译也检查不到的。

    常见可检查异常:Java编译器要求必须手动catch。

    • 操作数据库异常:SQLException
    • 输入输出异常:IOException
    • 文件未找到异常:FileNotFoundException
    • 反射操作异常:ReflectiveOperationException
    • 类未找到异常: ClassNotFoundException
    • 方法未找到异常:NoSuchMethodException
    • 字段未找到异常:NoSuchFieldException
    • 非法访问权限异常:IllegalAccessException
    • 实例化异常:InstantiationException
    • 不支持克隆异常:CloneNotSupportedException
    • 被中止异常:InterruptedException

    常见运行时异常: RuntimeExecption在java.lang包下。我们可以不处理,出现异常时由虚拟机接管。

    • 访问数组越界:ArrayIndexOutOfBoundsException  
    • 输入数据类型与声明不匹配:InputMismatchException  
    • 数学运算异常:ArithmeticException  
    • 类转换异常:ClassCastException
    • 空指针:NullPointException
    • 数据存储异常:ArrayStoreException

    详细参考博客:

    https://blog.csdn.net/yuwenlanleng/article/details/84646448

    https://blog.csdn.net/inflaRunAs/article/details/103542478

    抛出异常有三种形式:①系统自动抛出 throw throws 

    ①系统自动抛出

     1   import java.util.Scanner;
     2   public class Test {
     3   
     4       public static void main(String[] args) {
     5           Scanner input =new Scanner(System.in);
     6           System.out.println("请输入被除数:");
     7                  try {                     
     8                        int num1=input.nextInt();
     9                        System.out.println("请输入除数:");
    10                        int num2=input.nextInt();
    11                        System.out.println(String.format("%d / %d = %d",num1, num2, num1 / num2));
    12                   }catch (Exception e) {
    13                       System.err.println("出现错误:被除数和除数必须是整数,"+"除数不能为零。");
    14                       System.out.println(e.getMessage());
    15                   }
    16      }
    17  }

    运行结果:

    System.err.println:输出错误信息,控制台呈红色。

    当除数为0时,系统抛出异常,然后转而调用catch,catch捕捉到了异常进入catch内部执行。

    我们没有写throw语句抛出异常,当然try-catch也可以不用,试试效果。

     如果不用try、catch捕捉:

        import java.util.Scanner;
        public class Test {
            public static void main(String[] args) {
                Scanner input =new Scanner(System.in);
                System.out.println("请输入被除数:");           
                int num1=input.nextInt();
                System.out.println("请输入除数:");
                int num2=input.nextInt();
                System.out.println(String.format("%d / %d = %d",num1, num2, num1 / num2));
          }
      }

    运行结果:

     所以运行时异常是可以不用写throw语句的,调用层也可以不用try-catch。


     

    throw

    import java.util.Scanner;
    public class Run {
      public static int quotient(int number1,int number2) {
            if(number2==0) 
                throw new ArithmeticException("除数不能为零") ;
            return number1 /number2;
            }
        public static void main(String[] args) {
            Scanner input =new Scanner(System.in);
            System.out.println("请输入被除数:");
            try {                 
                int num1=input.nextInt();
                System.out.println("请输入除数:");
                int num2=input.nextInt();
                int result=quotient(num1,num2);//调用quotien()
                System.out.println(String.format("%d / %d = %d",num1, num2, result));
                }catch (ArithmeticException e) {
                    System.err.println("出现错误:被除数和除数必须是整数,"+"除数不能为零。");
                    System.out.println(e.getMessage());
                    }     
            System.out.println("继续...");
            }
    }

    运行结果:

     

    方法quotient来抛出异常,该异常可以被调用者捕获和处理。

    throw语句的执行称为抛出一个异常,异常类是java.lang.ArithmeticException。

    当异常被抛出,正常的执行流程就被中断,throw相当于调用catch块,如果类型匹配则执行执行catch块,执行完后不反回到throw语句,而是执行catch块后的下一语句。

    当然这个异常(ArithmeticException)是可以直接丢给系统抛出的,但是有些自定义异常就必须把抛出异常的方法写出来然后try-catch捕捉。

    比如自定义一个除数为奇数时抛出异常的例子:

    import java.util.Scanner;
    public class MyException extends ArithmeticException {//继承Exception也可以
        public MyException() {
            super();
        }
        public MyException(String s) {
            super(s);
        }
    }
    
    public class Run {
      public static int quotient(int number1,int number2) {
            if((number2%2)==1) 
                throw new MyException("除数不能为奇数") ;
            return number1 /number2;
            }
        public static void main(String[] args) {
            Scanner input =new Scanner(System.in);
            System.out.println("请输入被除数:");
            try {                 
                int num1=input.nextInt();
                System.out.println("请输入除数:");
                int num2=input.nextInt();
                int result=quotient(num1,num2);//调用quotien()
                System.out.println(String.format("%d / %d = %d",num1, num2, result));
                }catch(MyException e){//子类异常在父类之前,所以MyException要在前,避免覆盖。
    //如果MyException继承的是Exception,与ArithmeticException不构成父子关系,顺序就随便了。
    System.err.println("出现错误:除数不能为奇数。"); }catch (ArithmeticException e) { System.err.println("出现错误:被除数和除数必须是整数,"+"除数不能为零。"); System.out.println(e.getMessage()); } System.out.println("继续..."); } }

    运行结果:

     当除数为奇数时,quotien()方法抛出异常。第一次就是奇数抛异常然后被第一个catch捕获;第二次除数为0,系统会抛出运算异常(ArithmeticException)被第二个catch捕获。

    下面来修改程序,如果自定义异常继承Exception类:

    import java.util.Scanner;
    public class MyException extends Exception {//修改为继承Exception
        public MyException() {
            super();
        }
        public MyException(String s) {
            super(s);
        }
    }
    
    public class Run {
      public static int quotient(int number1,int number2) throws MyException {//必须加throws声明
            if((number2%2)==1) 
                throw new MyException("除数不能为奇数") ;
            return number1 /number2;
            }
        public static void main(String[] args) {
            Scanner input =new Scanner(System.in);
            System.out.println("请输入被除数:");
            try {                 
                int num1=input.nextInt();
                System.out.println("请输入除数:");
                int num2=input.nextInt();
                int result=quotient(num1,num2);//调用quotien()
                System.out.println(String.format("%d / %d = %d",num1, num2, result));
                }catch (ArithmeticException e) {
                    System.err.println("出现错误:被除数和除数必须是整数,"+"除数不能为零。");
                    System.out.println(e.getMessage());
                }catch(MyException e){//此时catch块顺序随意
                    System.err.println("出现错误:除数不能为奇数。");
                }         
            System.out.println("继续...");
            }
    }

    运行结果:

    现在又有新的疑问了——为什么抛出异常的方法头要有声明throws? 接着往下看!


    throws 

    throws就是声明一系列可能抛出的异常,多个异常逗号分开。

    1 public static int quotient(int number1,int number2) throws ArithmeticException{
    2         if(number1==0) 
    3             throw new ArithmeticException("除数不能为零") ;
    4         return number1 /number2;
    5     }

    然后回到之前问题:

    Excepiton分两类:checked exception、runtime exception;直接继承自Exception就是checked exception,继承自RuntimeException就是runtime的exception。

    checked exception就是要强制你去处理这个异常(不管throws多少层,终归要在某个地方catch它);而runtime exception则没有这个限制,可以自由选择是否catch。

    那些强制异常处理的代码块,必须进行异常处理,否则编译器会提示“Unhandled exception type Exception”错误警告。


    finally

    不论异常是否产生,finally子句总是会被执行。

        try {
            //
        }catch{
            //
        }finally {
            //此处代码都会执行
        }
  • 相关阅读:
    SharePoint 2013 图文开发系列之自定义字段
    SharePoint 2013 图文开发系列之Visual Studio 创建母版页
    SharePoint 2013 图文开发系列之代码定义列表
    SharePoint 2013 图文开发系列之计时器任务
    SharePoint 2013 图文开发系列之应用程序页
    SharePoint 2013 图文开发系列之事件接收器
    SharePoint 2013 图文开发系列之可视化WebPart
    SharePoint 2013 图文开发系列之WebPart
    SharePoint 2013 对二进制大型对象(BLOB)进行爬网
    SharePoint 2013 状态机工作流之日常报销示例
  • 原文地址:https://www.cnblogs.com/codercql/p/13394862.html
Copyright © 2011-2022 走看看