• 异常——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 {
            //此处代码都会执行
        }
  • 相关阅读:
    javascript插入样式
    Backbone.js使用jsonp api示例
    RequireJS optimizer Ant task
    Javascript 中的 call 和 apply
    通过shtml实现重构页面模块化构建的相关设置
    Eclipse 支持JQuery提示 jQueryWTP插件的安装方法
    iframe加载完成监控兼容IE/FF/Chrome
    让浏览器跨域
    Javascript 类的实现
    宏定义和内联函数区别
  • 原文地址:https://www.cnblogs.com/codercql/p/13394862.html
Copyright © 2020-2023  润新知