zoukankan      html  css  js  c++  java
  • 08java进阶——异常

    1.异常的概念

    package cn.jxufe.java.chapter08.demo01;
    
    public class Test01ArithmeticException {
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            division(30, 3);
            division(30, 0);
        }
    
        public static void division(int a, int b) {
            System.out.println("计算除法");
            System.out.println("结果。。。" + a / b);
        }
    }

    2.异常类

    3.异常和错误的区别

    异常:指程序在编译、运行期间发生了某种异常(XxxException),我们可以对异常进行具体的处理。若不处理异常,程序将会结束运行。

    错误:指程序在运行期间发生了某种错误(XxxError),Error错误通常没有具体的处理方式,程序将会结束运行。Error错误的发生往往都是系统级别的问题,都是jvm所在系统发生的,并反馈给jvm的。我们无法针对处理,只能修正代码。

    package cn.jxufe.java.chapter08.demo01;
    
    public class Test02ExceptionAndError {
    
        /*
         * Throwable
         *  Exception 异常   感冒,阑尾炎
         *    将异常处理掉,可以继续执行
         *    RuntimeException
         *  Error 非典,艾滋,癌
         *    必须修改程序
         */
        public static void main(String[] args) {
            int[] arr = new int[999999999];//错误,没有那么大的堆内存
            System.out.println(arr[3]);
    
        }
    
    }

    4.异常对象的产生和处理流程

    5.抛出异常throw和throws

    在编写程序时,我们必须要考虑程序出现问题的情况。比如,在定义方法时,方法需要接受参数。那么,当调用方法使用接受到的参数时,首先需要先对参数数据进行合法的判断,数据若不合法,就应该告诉调用者,传递合法的数据进来。这时需要使用抛出异常的方式来告诉调用者。

    在java中,提供了一个throw关键字,它用来抛出一个指定的异常对象。那么,抛出一个异常具体如何操作呢?

    •  1,创建一个异常对象。封装一些提示信息(信息可以自己编写)。
    •  2,需要将这个异常对象告知给调用者。怎么告知呢?怎么将这个异常对象传递到调用者处呢?通过关键字throw就可以完成。throw 异常对象;

    throw用在方法内,用来抛出一个异常对象,将这个异常对象传递到调用者处,并结束当前方法的执行。

    使用格式:

    throw new 异常类名(参数);

    例如:
    throw new NullPointerException("要访问的arr数组不存在");
    throw new ArrayIndexOutOfBoundsException("该索引在数组中不存在,已超出范围");

    声明:将问题标识出来,报告给调用者。如果方法内通过throw抛出了编译时异常,而没有捕获处理(稍后讲解该方式),那么必须通过throws进行声明,让调用者去处理。

    声明异常格式:

    修饰符 返回值类型 方法名(参数) throws 异常类名1,异常类名2… {   }

    package cn.jxufe.java.chapter08.demo01;
    
    public class Test03Throw {
    
        public static void main(String[] args) throws Exception {
            // TODO Auto-generated method stub
            int[] arr = {};
            int temp = getArray(arr);
        }
    
        public static int getArray(int[] arr) throws Exception {
            // 对方法参数进行合法性的判断,进行判断是不是null
            if (arr == null) {
                // 抛出异常的形式,告诉调用者
                // 关键字 throw
                throw new Exception("数组不存在");
            }
            // 对数组进行判断,判断数组中,是不是有元素
            if (arr.length == 0) {
                // 抛出异常的形式,告诉调用者,数组没有元素
                throw new Exception("数组中没有元素");
            }
            int i = arr[arr.length - 1];
            return 2 * i;
        }
    }

    6.try-catch-finally捕获异常

    捕获异常格式:
    try {
        //需要被检测的语句。
    }
    catch(异常类 变量) { //参数。
        //异常的处理语句。
    }
    finally {
        //一定会被执行的语句。
    }

    try:该代码块中编写可能产生异常的代码。

    catch:用来进行某种异常的捕获,实现对捕获到的异常进行处理。

    finally有一些特定的代码无论异常是否发生,都需要执行。另外,因为异常会引发程序跳转,导致有些语句执行不到。而finally就是解决这个问题的,在finally代码块中存放的代码都是一定会被执行的。

    package cn.jxufe.java.chapter08.demo01;
    
    public class Test04TryCatchFinally {
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            int[] arr = null;
            try {
                int i = getArray(arr);
                System.out.println(i);
    
            } catch (NullPointerException ex) {
                System.out.println("###" + ex);
    
            } catch (ArrayIndexOutOfBoundsException ex) {
    
                System.out.println("!!!!!!" + ex);
            }
            System.out.println("Game Over");
        }
    
        /*
         * 定义方法,抛出异常
         * 调用者使用try catch
         */
        public static int getArray(int[] arr) throws NullPointerException, ArrayIndexOutOfBoundsException {
            // 对数组判空
            if (arr == null) {
                // 手动抛出异常,抛出空指针异常
                throw new NullPointerException("数组不存在");
            }
            // 对数组的索引进行判断
            if (arr.length < 3) {
                // 手动抛出异常,抛出数组的索引越界异常
                throw new ArrayIndexOutOfBoundsException("数组没有3索引");
            }
            return arr[3] + 1;
        }
    }

    7.多个异常处理的细节

    package cn.jxufe.java.chapter08.demo01;
    
    /*
     *  多catch写在一起
     *  细节:
     *    catch小括号中,写的是异常类的类名
     *    有没有顺序的概念,有
     *    
     *    平级异常: 抛出的异常类之间,没有继承关系,没有顺序
     *      NullPointerException extends RuntimeException
     *      NoSuchElementException extends RuntimeException
     *      ArrayIndexOutOfBoundsException extends IndexOutOfBoundsException extends RuntimeException
     *      
     *    上下级关系的异常
     *      NullPointerException extends RuntimeException extends Exception
     *      越高级的父类,写在下面
     */
    public class Test05Catch {
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            try {
    
            } catch (NullPointerException ex) {
    
            } catch (Exception ex) {
    
            }
        }
    
        public static void function(int a) throws NullPointerException, Exception {
            if (a == 0) {
                throw new NullPointerException();
            }
            if (a == 1) {
                throw new Exception();
            }
        }
    }

    8.运行异常

    package cn.jxufe.java.chapter08.demo01;
    
    import java.util.Scanner;
    /*
     *  异常分为编译异常和运行时期异常
     *    编译异常: 调用了抛出异常的方法,不处理编译失败  (try  throws)
     *    运行异常: 抛出的异常是RuntimeException类,或者是他的子类
     *  
     *  运行异常的特点:
     *     方法内部抛出的异常是运行异常, new XXXException
     *     方法的声明上,不需要throws语句,调用者,不需要处理
     *     设计原因:
     *        运行异常,不能发生,但是如果发生了,程序人员停止程序修改源代码
     *        
     *        运行异常: 一旦发生,不要处理,请你修改源代码, 运行异常一旦发生,后面的代码没有执行的意义
     */
    public class Test06QuotientWtihException {
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            Scanner input = new Scanner(System.in);
            System.out.println("enter two integers: ");
            int number1 = input.nextInt();
            int number2 = input.nextInt();
            try {
                int result = quotient(number1, number2);
                System.out.println(number1 + " / " + number2 + " is " + result);
    
            } catch (ArithmeticException e) {
                // TODO: handle exception
                System.out.println(e+"不能除以0");
            }
        }
    
        public static int quotient(int number1, int number2) {//不用声明异常
            if (number2 == 0)
                throw new ArithmeticException("Divisor cannot be zero");//ctrl+T查看继承关系:运行异常,不用声明异常
            return number1 / number2;
        }
    }

     运行异常的案例

    package cn.jxufe.java.chapter08.demo01;
    
    public class Test07RuntimeException {
    
        public static void main(String[] args)  {
            // TODO Auto-generated method stub
            double d = 0;
            try {
                d = getArea(-1);
            } catch (Exception e) {
                // TODO Auto-generated catch block
            }
            System.out.println(d);
        }
        /*
         *  定义方法,计算圆形的面积
         *  传递参数0,或者负数,计算的时候没有问题
         *  但是,违反了真实情况
         *  参数小于=0, 停止程序,不要在计算了
         */
        public static double getArea(double r) throws Exception{
            if(r <= 0)
                throw new Exception("圆形不存在");
            return r*r*Math.PI;
        }
    }

    这个例子说明,有些参数有问题,导致后面的程序无法计算了,那么就应该用RuntimeException。

    package cn.jxufe.java.chapter08.demo01;
    
    public class Test07RuntimeException {
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            double d = getArea(-1);
            System.out.println(d);
        }
    
        /*
         *  定义方法,计算圆形的面积
         *  传递参数0,或者负数,计算的时候没有问题
         *  但是,违反了真实情况
         *  参数小于=0, 停止程序,不要在计算了
         */
        public static double getArea(double r) {
            if (r <= 0)
                throw new RuntimeException("圆形不存在");
            return r * r * Math.PI;
        }
    }

    9.使用异常的好处

    package cn.jxufe.java.chapter08.demo01;
    
    import java.util.InputMismatchException;
    import java.util.Scanner;
    
    public class Test08MismatchException {
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            Scanner input = new Scanner(System.in);
            boolean continueInput = true;
            System.out.println("enter an integer:");
            do {
                try {
                    int number = input.nextInt();
                    System.out.println("the number entered is " + number);
                    continueInput = false;
                    
                } catch (InputMismatchException e) {
                    // TODO: handle exception
                    System.out.println("try again : an integer is required ");
                    input.nextLine(); //输入不合法可以连续输入
                }
            } while (continueInput);
            System.out.println("输入完成。。。");
        }
    }

    10.从异常中获取信息

    package cn.jxufe.java.chapter08.demo01;
    
    import com.sun.management.jmx.Trace;
    
    public class Test09Exception {
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            try {
                System.out.print(sum(new int[] {1,2,3,4,5}));
            } catch (Exception e) {
                // TODO: handle exception
                e.printStackTrace();
                System.out.println("
    "+ e.getMessage());
                System.out.println("
    " + e.toString());
                
                System.out.println("
    Trace Info Obtained from getStackTrace");
                StackTraceElement[] stackTraceElements = e.getStackTrace();
                for (int i = 0; i < stackTraceElements.length; i++) {
                    System.out.println("method " + stackTraceElements[i].getMethodName());
                    System.out.println("(" + stackTraceElements[i].getClassName()+":");
                    System.out.println(stackTraceElements[i].getLineNumber()+")");
                    
                }
            }
        }
    
        public static int sum(int[] list) {
            int result = 0;
            for (int i = 0; i <= list.length; i++) { //有一个<=的异常
                result += list[i];
            }
            return result;
        }
    }

    11.异常在方法重写中的细节

    • 子类覆盖父类方法时,如果父类的方法声明异常,子类只能声明父类异常或者该异常的子类,或者不声明。
    例如:
    class Fu {
        public void method () throws RuntimeException {
    }
    }
    class Zi extends Fu {
        public void method() throws RuntimeException { }  //抛出父类一样的异常
        //public void method() throws NullPointerException{ } //抛出父类子异常
    }
    • 当父类方法声明多个异常时,子类覆盖时只能声明多个异常的子集。
    例如:
    class Fu {
        public void method () throws NullPointerException, ClassCastException{
    }
    }
    class Zi extends Fu {
        public void method()throws NullPointerException, ClassCastException { }          public void method() throws NullPointerException{ } //抛出父类异常中的一部分
        public void method() throws ClassCastException { } //抛出父类异常中的一部分
    }
    • 当被覆盖的方法没有异常声明时,子类覆盖时无法声明异常的。
    例如:
    class Fu {
        public void method (){
    }
    }
    class Zi extends Fu {
        public void method() throws Exception { }//错误的方式
    }

    举例:父类中会存在下列这种情况,接口也有这种情况

    问题:接口中没有声明异常,而实现的子类覆盖方法时发生了异常,怎么办?

    答:无法进行throws声明,只能catch的捕获。万一问题处理不了呢?catch中继续throw抛出,但是只能将异常转换成RuntimeException子类抛出。

    interface Inter {
        public abstract void method();
    }
    class Zi implements Inter {
        public void method(){ //无法声明 throws Exception
            int[] arr = null;
            if (arr == null) {
                //只能捕获处理
                try{
    throw new Exception(“哥们,你定义的数组arr是空的!”);
    } catch(Exception e){
        System.out.println(“父方法中没有异常抛出,子类中不能抛出Exception异常”);
            //我们把异常对象e,采用RuntimeException异常方式抛出
            throw new RuntimeException(e);
    }
    }
    }
    }

    12.自定义异常

    通过阅读异常源代码:发现java中所有的异常类,都是继承Throwable,或者继承Throwable的子类。这样该异常才可以被throw抛出。

    说明这个异常体系具备一个特有的特性:可抛性:即可以被throw关键字操作。

    并且查阅异常子类源码,发现每个异常中都调用了父类的构造方法,把异常描述信息传递给了父类,让父类帮我们进行异常信息的封装。

    例如NullPointerException异常类源代码:
    public class NullPointerException extends RuntimeException {
        public NullPointerException() {
            super();//调用父类构造方法
        }
        public NullPointerException(String s) {
            super(s);//调用父类具有异常信息的构造方法
        }
    }
    package cn.jxufe.java.chapter08.demo01;
    
    public class Test10OurClassException {
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            int avg = getAvg(50, 60, -70, 80);
            System.out.println(avg);
        }
    
        /*
         * 传递成绩,计算成绩的平均数
         * 成绩没有负数,需要抛出异常,停止运算
         */
        public static int getAvg(int... source) {
            int sum = 0;
            for (int s : source) {
                if (s < 0) {
                    throw new FuShuException("成绩错误 " + s);
                }
                sum = sum + s;
            }
            return sum / source.length;
        }
    }
    
    /*
     *  自定义异常
     *    继承Exception,或者继承RuntimeException
     *    构造方法中,super将异常信息,传递给父类
     */
    class FuShuException extends RuntimeException {
        public FuShuException(String s) {
            super(s);
        }
    
        public FuShuException() {
        }
    }

  • 相关阅读:
    POJ 1731
    POJ 1256
    POJ:1833 按字典序找到下一个排列:
    git工作流
    git 分之合并和冲突解决
    iis 7 操作 .net
    IIS7.0 Appcmd 命令详解
    SQL的注入式攻击方式和避免方法
    实例详解Django的 select_related
    django-ajax之post方式
  • 原文地址:https://www.cnblogs.com/xinmomoyan/p/10958363.html
Copyright © 2011-2022 走看看