异常的体系结构,产生原因,抛异常 ,异常的处理。全面的总结

 java中,程序运行过程中产生的问题叫做异常,在java中所有程序运行产生的问题都可以用一个类来表示,这个类叫做它Throwable,它有两个子类
Error:表示错误,程序中出现了不可挽回问题
Exception:表示异常,程序中出现的可以挽救补回的问题
 
 

异常产生原因流程

/*
    throw关键字,可以手动的抛出一个异常对象。

    格式:
        throw new 异常类();

    注意:
        只有异常体系下的类才具有可抛性。
        一旦某个方法抛出异常,后面的代码都不会再执行了
 */
public class Demo03Throw {
    public static void main(String[] args) {
        int[] a = new int[10]; //定义一个数组
        int value = getValue(a, 10);//调用getValue获取数组指定索引的元素
        System.out.println("value:" + value);
    }

    public static int getValue(int a[], int num) {
        if (num < 0 || num > a.length - 1) {
            //进行判断,如果num索引在一个不合法的范围内,那么就抛出异常
            String msg = "这是一个数组越界异常";
            throw new ArrayIndexOutOfBoundsException(msg);
        }
        System.out.println("你好");//并不会执行,因为之前抛了一个异常
        return a[num];

    }

}
/* 空指针异常:
    Objects里面有一个方法,可以判断一个对象是否是null,如果是null会直接抛出一个空指针异常。

        static <T> T requireNonNull​(T obj):判断指定的对象是否是null
        static <T> T requireNonNull​(T obj, String message): 第二个参数message表示异常信息。
 */
public class Demo04Objects {
    public static void main(String[] args) {
        Object obj = null;
      /*  if(obj==null) 
        {
            throw new NullPointerException("某个对象的值为null");
        }*/手动抛异常的方法
//      Objects.requireNonNull(obj);//objects中的方法1
        Objects.requireNonNull(obj, "这是一个空指针异常");//objects中的方法2
        obj.toString();
        System.out.println("sdf" + obj);

    }
}
结果:Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 这是一个数组越界异常
 at demo01exception.Demo03Throw.getValue(Demo03Throw.java:24)
 at demo01exception.Demo03Throw.main(Demo03Throw.java:16)

/* throw:手动的创建一个异常对象并抛出。是抛出
throws: 用来声明这个方法可能会抛出一个异常。

throws使用格式

修饰符 返回值类型 方法名(参数列表) throws 异常类名{
      方法体;
      return 返回值;
   }
 
注意:
1. 如果一个方法内抛出了编译时异常,那么一定要在这个方法上面加上throws异常声明。(也可以try...catch
 2. 如果方法内抛出的是运行时异常, 那么可以是使用throws声明,也可以不使用。
 3. 如果一个方法内抛出了多个异常,可以使用throws关键字声明这个方法会抛出多个异常。
4. 如果一个方法可能抛出多个异常,那么除了第3种做法之外,也可以使用throws声明他
们的父类异常。
            */
public class Demo05Throws {
       public static void main(String[] args) {


       }
    // 4. 如果一个方法可能抛出多个异常,那么除了第3种做法之外,也可以使用throws声明他们的父类异常。
    public static void method4() throws Exception{
        int i = 1;
        if(i % 2 == 0) {
            throw new IOException();
        } else {
            throw new ClassNotFoundException();
        }
    }
    //如果一个方法内抛出了多个异常,可以使用throws关键字声明这个方法会抛出多个异常。
    public static void method3() throws IOException, ClassNotFoundException{
        int i = 1;
        if(i % 2 == 0) {
            throw new IOException();
        } else {
            throw new ClassNotFoundException();
        }
    }
    //如果方法内抛出的是运行时异常, 那么可以是使用throws声明,也可以不使用。
    public static void method2() {
        throw new ArrayIndexOutOfBoundsException();
    }

       public static void method()throws IOException{
//手动抛出一个编译异常
//编译时异常是 ExceptionException下面除了RuntimeException之外的其他子类
       }
   }
/*  如果遇到异常之后,不希望把异常往外抛, 希望自己解决这个异常,那么可以使用try...catch关键字。

    格式:
  try {
        1. 要检测的代码
    } catch(异常类名 变量名) {
        2. 异常的处理方式的代码。
    }

执行流程:
1. 会执行try中的代码,如果try中的代码没有出现异常,那么就会跳过catch往下执行。
2. 如果try中的代码出现了异常,并且catch捕获到了这个异常,那么就执行执行catch中的语句。

    注意:
       1. 如果try中的代码出现了问题,那么如果catch捕获到了这个异常,会直接进入到catch中。
       2. 如果try中的代码出现了问题,但是catch并没有捕获到,那么这个异常会依旧抛给调用者。
总结:
    异常有两种处理方式
        1. 往外抛(甩锅)
          throw, throws
        2. 自己真正的把这个异常给解决了
          try...catch
                    */
public class Demo06TryCatch {
    public static void main(String[] args) {
        try {
            Object obj = null;
            obj.toString();
            System.out.println("1........try");

        } catch (Exception e) {
            System.out.println("2.catch");

        }
        System.out.println("2.catch---------");
    }
}
*    try...catch...finally

格式:
   try {
    A. 要检测可能会出现异常的代码】
       } 
catch(异常类名 变量名){
    B.出现异常之后该怎么做的代码】
      } finally {
            C. 一定会执行的代码 】
        }
        注意:
        不管程序结果如何,finally代码块一定会执行。

        执行流程:
        假如try中的代码没有出现异常: 【A】【C        假如try中的代码出现了异常并且catch捕获到了这个异常: 【A】【B】【C        假如try中的代码出现了异常但是catch没有捕获到: 【A】【C】【把异常抛给调用者】

        finally代码块不管怎样一定会执行。

        finally代码块的使用场景。
        一般用在释放资源。比如后期IO流释放资源,jdbc释放连接....

        */
public class Demo07TryCatchFinally {
    public static void main(String[] args) {
        try {
            System.out.println("1...try start");
            Object obj = null;
            obj.toString();
            System.out.println("2...tryend");


        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("3..catch");
        } finally {
            System.out.println("4...finally");
        }

    }
}
/*运行时异常和编译时异常的区别。

  运行时异常: 指的是RuntimeException以及RuntimeException下面的所有子类。
  编译时异常: 指的是Exception以及Exception下面除了RuntimeException之外的其他子类。

 区别:
     编译时异常: 当一个方法内抛出编译时异常,必须要进行处理。要么使用throws声明这个方法会抛出异常。要么使用trycatch直接把这个异常解决掉。
     
    运行时异常: 一个方法抛出运行时异常,可以处理,也可以不处理。


 如果希望让调用者知道自己这个方法可能会出现问题,那么最好用编译时异常。
如果不想让调用者知道我这个方法会有问题,那么可以使用运行时异常。
          */
public class Demo08RunTimeException {
    public static void main(String[] args) {

        //运行时异常: 一个方法抛出运行时异常,可以处理,也可以不处理。
        method2();
        //如果运行时异常没有处理,等到程序运行的时候也会把这个异常抛给调用者。

    }
      public static void method2() {
          throw new RuntimeException();
      }

      public static void method1() {
          try {
              //抛出一个编译时异常
              throw new Exception();
          } catch (Exception e) {

          }
      }
  }
/*多个catch的异常处理方式

    try {
        要检测的代码
    } catch(要捕获的异常 变量名) {
        如果出现该异常对应的解决方案
    } catch(要捕获的异常 变量名) {
        如果出现该异常对应的解决方案
    } catch(要捕获的异常 变量名) {
        如果出现该异常对应的解决方案
    }


执行流程:
    如果try中的代码出现了问题,那么哪一个catch先捕获到,那么就执行哪个catch中的代码。
    如果try中的代码没有任何问题,那么所有的catch都不执行。

注意事项:
        如果使用多个catch捕获异常,那么父类异常不能放在子类异常的前面。因为子类异常能捕获到的,父类异常一定也可以捕获到,如果把父类异常放前面。父类异常会捕到所有的导致子类异常没有东西可以捕获。
 */


public class Demo09TryCatchCatch {
    public static void main(String[] args) {
        try {
            Object obj = null;
            obj.toString();
            System.out.println("1. try...end");
        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("2. ArrayIndexOutOfBoundsException");
        } catch (NullPointerException e) {
            System.out.println("3. NullPointerException");
        } catch (Exception e) {
            System.out.println("4. Exception");
        }
    }
}
/*
 模拟注册的练习,定义方法,用来注册,如果这个注册的用户名已经存在,抛出异常。
 */
public class Demo01ExceptionTest {
    private static String[] name = {"lalfa", "fas", "fdsf", "adbd"};

    public static void main(String[] args) {
        // 定义数组,当做数据库,用来保存已经存在的用户名
        try {
            //进行注册
            regist("fas");
            System.out.println("注册成功");
        } catch (RegistException e) {
            System.out.println(e.getMessage());
        } catch (Exception e)

        {
            System.out.println("出现了其他问题");
            e.printStackTrace();
        }
    }

    /*
        定义一个方法,用来注册
        参数是一个字符串,表示要注册的用户名
        如果此用户名已经存在,那么就以抛出异常的方式提示注册失败。*/
    public static void regist(String user) {
        for (String username : name) {
            if (user.equals(username)) {
                throw new RegistException("用户名" + user + "已经存在");
     //抛的异常类型为自定义类型,需要创建一个类去继承任意异常       }
        }
    }

}
//自定义的异常
/*    如何自定义一个异常?        认贼作父。 找一个异常类当做父类。
    如果使用一个类继承了异常类,那么这个类也就变成了异常类。
    如果这个类继承的是编译时异常,那么这个类就会变成编译时异常类。    如果这个类继承的是运行时异常,那么这个类就会变成运行时异常类。
 */
//定义注册异常
public class RegistException extends RuntimeException {
    public RegistException() {

    }

    public RegistException(String Message) {
        super(Message);
    }
}



猜你喜欢

转载自blog.csdn.net/qq_28761767/article/details/80989122